似乎没有块门。
这题分块也是可以做的,时间复杂度 \(O(n\sqrt n)\) 是大手子 @ 在场上想出来的,非常浅显易懂也好码。
首先对修改分块,每一次修改到块的最右边的时候,对块进行构造。具体的说,将块内修改的 \(l\) 和 \(r+1\) 离散化并且记录 \(1\sim n\) 每一个点的上一个在块内出现过的值。最后直接块内暴力修改。
一个 build 的时间复杂度是 \(O(n)\) 的因为出现过的值的数量是 O(\sqrt n),而修改的数量也是 \(O(\sqrt n)\)。
query 是 naive 的,自己推一下就行,不行的话就看代码。
c++
//去了缺省源
const int N = 1e5 + 5,B = 405;
int n, q, vval[N], feat, mod, tim, ans;
int L[N],R[N],bel[N];
int qpow(int x, int y = mod - 2) {
int res = 1;
while (y) {
if (y & 1)
res = res * x % mod;
y >>= 1;
x = x * x % mod;
}
return res;
}
struct Data {
int k, b;
Data(int x = 0) {
k = b = 0;
if (x == 1) k = 1;
}
Data(int _k, int _b) { k = _k, b = _b; }
__inline friend Data operator*(const Data &a, const Data &b) {
return Data(Mod.f(1ll * a.k * b.k), Mod.f(1ll * a.b * b.k + b.b));
}
}val[B][B*2];
struct P{
int l,r,x,y;
}a[N];
int tot,tmp[N];
int lst[B][N];
void build(int belong){
tot=0;
for(int i=L[belong];i<=R[belong];i++){
tmp[++tot] = a[i].l;
tmp[++tot] = a[i].r+1;
}
sort(tmp+1,tmp+tot+1);
tot=unique(tmp+1,tmp+tot+1)-tmp-1;
for(int i=1;i<=n;i++)lst[belong][i] = -1;
for(int i=1;i<=tot;i++)lst[belong][tmp[i]] = i;
for(int i=1;i<=n;i++)if(lst[belong][i]==-1)lst[belong][i] = lst[belong][i-1];
for(int i=0;i<=tot;i++)val[belong][i] = Data(1);
for(int i=L[belong];i<=R[belong];i++){
int l = lower_bound(tmp+1,tmp+tot+1,a[i].l)-tmp;
int r = lower_bound(tmp+1,tmp+tot+1,a[i].r+1)-tmp-1;
for(int j=l;j<=r;j++)val[belong][j]=val[belong][j]*Data(a[i].x ,a[i].y);
}
}
int query(int l,int r,int x){
Data ans(0,vval[x]);
if(bel[l]==bel[r]){
for(int i=l;i<=r;i++) if(a[i].l<=x && x<=a[i].r)ans = ans*Data(a[i].x ,a[i].y);
return ans.b;
}
for(int i=l;i<=R[bel[l]];i++) if(a[i].l<=x && x<=a[i].r )ans = ans* Data(a[i].x,a[i].y );
for(int i=bel[l]+1;i<bel[r];i++)ans = ans * val[i][lst[i][x]];
for(int i=L[bel[r]];i<=r;i++) if(a[i].l<=x && x<=a[i].r )ans = ans* Data(a[i].x,a[i].y );
return ans.b;
}
signed main() {
// freopen("ex_input3.txt","r",stdin);
// freopen("ex_ansput3.txt","w",stdout);
read(feat);
read(n), read(mod);
Mod = FastMod(mod);
for (int i = 1; i <= n; i++) read(vval[i]);
read(q);
for(int i=1;i<=100000;i++){
bel[i] = (i-1)/B+1;
if(!L[bel[i]])L[bel[i]] = i;
R[bel[i]] = i;
}
for (int i = 1; i <= q; i++) {
int opt, l, r, x, y;
read(opt);
if (opt == 1) {
++tim;
read(a[tim].l), read(a[tim].r), read(a[tim].x), read(a[tim].y);
if (feat & 1)
a[tim].l ^= ans, a[tim].r ^= ans;
if(tim == R[bel[tim]]) build(bel[tim]);
} else {
read(l), read(r), read(x);
if (feat & 1)l ^= ans, r ^= ans, x ^= ans;
put(ans=query(l, r, x));
}
}
return 0;
}