Luogu P11721 题解

似乎没有块门。

这题分块也是可以做的,时间复杂度 \(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;
}