BZOJ2877:[NOI2012]魔幻棋盘

浅谈树状数组与主席树:https://www.cnblogs.com/AKMer/p/9946944.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=2877

这就是个屎题。

而且至今我还不知道为什么洛谷和本地都可以过但是(BZOJ)(RE)

利用更相减损数以棋盘守护者为中心进行二维差分,那么每次修改就变成若干个点的值的修改了。

然后二维线段树维护差分值。

详细一点你们可以看这个博客(我是懒得搞了):http://www.cnblogs.com/milky-w/p/8530723.html

反正我是不想再来回头看这题了,简直屎得一批。

2019.01.03更新:递归版代码开O3可以在BZOJ过,所以我觉得是递归的锅,果然把所有递归全部改成非递归就可以过了。还是清楚为什么递归层数并不多会RE。

时间复杂度:(O(nmlognlogm))

空间复杂度:(O(mn))

非递归版代码如下:

#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn=5e5+5;

int n,m,X,Y,T;
ll a[maxn],b[maxn];

ll read() {
	ll x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

ll gcd(ll a,ll b) {
	while(b) {
		ll tmp=b;b=a%b;
		a=tmp;
	}
	return abs(a);
}

struct tree_node {
	int p,l,r;

	tree_node () {}

	tree_node (int _p,int _l,int _r) {
		p=_p,l=_l,r=_r;
	}
};

struct segment_tree_y {
	int tot,top;
	tree_node sta[maxn<<1];
	int ls[maxn<<2],rs[maxn<<2];
	ll val[maxn<<2],ans[maxn<<2];
	int rt1[maxn<<1],rt2[maxn<<1];
	
	void build(int root,int x) {
		sta[++top]=tree_node(root,1,m);
		int now=1;
		while(now<=top) {
			if(sta[now].l==sta[now].r) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			ls[sta[now].p]=++tot,rs[sta[now].p]=++tot;
			sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
			sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
			now++;
		}
		while(top) {
			tree_node tmp=sta[top--];
			if(tmp.l==tmp.r)val[tmp.p]=a[(x-1)*m+tmp.l];
			else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
		}
	}

	void update(int root,int root1,int root2) {
		sta[++top]=tree_node(root,1,m);
		rt1[top]=root1,rt2[top]=root2;
		int now=1;
		while(now<=top) {
			if(sta[now].l==sta[now].r) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			ls[sta[now].p]=++tot,rs[sta[now].p]=++tot;
			sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
			rt1[top]=ls[rt1[now]],rt2[top]=ls[rt2[now]];
			sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
			rt1[top]=rs[rt1[now]],rt2[top]=rs[rt2[now]];
			now++;
		}
		while(top) {
			tree_node tmp=sta[top];
			int u=rt1[top],v=rt2[top];top--;
			if(tmp.l==tmp.r)val[tmp.p]=gcd(val[u],val[v]);
			else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
		}
	}

	ll query(int rt,int L,int R) {
		sta[++top]=tree_node(rt,1,m);
		int now=1;
		while(now<=top) {
			if(L<=sta[now].l&&sta[now].r<=R) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			if(L<=mid)sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
			if(R>mid)sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
			now++;
		}
		while(top) {
			tree_node tmp=sta[top--];
			if(L<=tmp.l&&tmp.r<=R)ans[tmp.p]=val[tmp.p];
			else {
				ans[tmp.p]=0;
				int mid=(tmp.l+tmp.r)>>1;
				if(L<=mid)ans[tmp.p]=ans[ls[tmp.p]];
				if(R>mid)ans[tmp.p]=gcd(ans[tmp.p],ans[rs[tmp.p]]);
			}
		}
		return ans[rt];
	}
	
	void change(int p,int pos,ll v,bool opt) {
		sta[++top]=tree_node(p,1,m);
		int now=1;
		while(now<=top) {
			if(sta[now].l==sta[now].r) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			if(pos<=mid)sta[++top]=tree_node(ls[sta[now].p],sta[now].l,mid);
			else sta[++top]=tree_node(rs[sta[now].p],mid+1,sta[now].r);
			now++;
		}
		while(top) {
			tree_node tmp=sta[top--];
			if(tmp.l==tmp.r) {
				if(opt)val[tmp.p]+=v;
				else val[tmp.p]=v;
			}
			else val[tmp.p]=gcd(val[ls[tmp.p]],val[rs[tmp.p]]);
		}
	}
}T2;

struct segment_tree_x {
	int top;
	int rt[maxn<<2];
	ll ans[maxn<<2];
	tree_node sta[maxn<<1];
	
	void build() {
		sta[++top]=tree_node(1,1,n);
		int now=1;
		while(now<=top) {
			if(sta[now].l==sta[now].r) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
			sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
			now++;
		}
		while(top) {
			tree_node tmp=sta[top--];rt[tmp.p]=++T2.tot;
			if(tmp.l==tmp.r)T2.build(rt[tmp.p],tmp.l);
			else T2.update(rt[tmp.p],rt[tmp.p<<1],rt[tmp.p<<1|1]);
		}
	}

	ll query(int x1,int x2,int y1,int y2) {
		sta[++top]=tree_node(1,1,n);
		int now=1;
		while(now<=top) {
			if(x1<=sta[now].l&&sta[now].r<=x2) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			if(x1<=mid)sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
			if(x2>mid)sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
			now++;
		}
		while(top) {
			tree_node tmp=sta[top--];
			if(x1<=tmp.l&&tmp.r<=x2)ans[tmp.p]=T2.query(rt[tmp.p],y1,y2);
			else {
				ans[tmp.p]=0;int mid=(tmp.l+tmp.r)>>1;
				if(x1<=mid)ans[tmp.p]=ans[tmp.p<<1];
				if(x2>mid)ans[tmp.p]=gcd(ans[tmp.p],ans[tmp.p<<1|1]);
			}
		}
		return ans[1];
	}

	void add(int x,int y,ll v) {
		if(x<1||x>n||y<1||y>m)return;
		sta[++top]=tree_node(1,1,n);
		int now=1;
		while(now<=top) {
			if(sta[now].l==sta[now].r) {now++;continue;}
			int mid=(sta[now].l+sta[now].r)>>1;
			if(x<=mid)sta[++top]=tree_node(sta[now].p<<1,sta[now].l,mid);
			else sta[++top]=tree_node(sta[now].p<<1|1,mid+1,sta[now].r);
			now++;
		}
		while(top) {
			tree_node tmp=sta[top--];
			if(tmp.l==tmp.r)T2.change(rt[tmp.p],y,v,1);
			else {
				ll lv=T2.query(rt[tmp.p<<1],y,y);
				ll rv=T2.query(rt[tmp.p<<1|1],y,y);
				T2.change(rt[tmp.p],y,gcd(lv,rv),0);
			}
		}
	}
}T1;

int main() {
	n=read(),m=read(),X=read(),Y=read(),T=read();
	for(int i=1;i<=n*m;i++)a[i]=read();
	for(int i=1;i<=n*m;i++) {
		int pos=(i-1)%m+1;
		if(pos<Y)b[i]=a[i]-a[i+1];
		else if(pos>Y)b[i]=a[i]-a[i-1];
		else b[i]=a[i];
	}
	for(int i=1;i<=n*m;i++) {
		int pos=(i-1)/m+1;
		if(pos<X)a[i]=b[i]-b[i+m];
		else if(pos>X)a[i]=b[i]-b[i-m];
		else a[i]=b[i];
	}
	T1.build();
	while(T--) {
		int opt=read(),x1=read(),y1=read(),x2=read(),y2=read();
		if(!opt) {
			x1=X-x1,x2=X+x2,y1=Y-y1,y2=Y+y2;
			printf("%lld
",T1.query(x1,x2,y1,y2));
		}
		if(opt) {
			ll val=read();
			if(x1<=X&&x2>=X&&y1<=Y&&y2>=Y) {
				T1.add(X,Y,val);
				T1.add(x1-1,y1-1,val);
				T1.add(x1-1,y2+1,val);
				T1.add(x2+1,y1-1,val);
				T1.add(x2+1,y2+1,val);
				T1.add(x1-1,Y,-val);
				T1.add(x2+1,Y,-val);
				T1.add(X,y1-1,-val);
				T1.add(X,y2+1,-val);
			}
			else if(y1<=Y&&y2>=Y) {
				if(x1<X) {
					T1.add(x2,Y,val);
					T1.add(x1-1,y1-1,val);
					T1.add(x1-1,y2+1,val);
					T1.add(x1-1,Y,-val);
					T1.add(x2,y1-1,-val);
					T1.add(x2,y2+1,-val);
				}
				else {
					T1.add(x1,Y,val);
					T1.add(x2+1,y1-1,val);
					T1.add(x2+1,y2+1,val);
					T1.add(x2+1,Y,-val);
					T1.add(x1,y1-1,-val);
					T1.add(x1,y2+1,-val);
				}
			}
			else if(x1<=X&&x2>=X) {
				if(y1<Y) {
					T1.add(X,y2,val);
					T1.add(x1-1,y1-1,val);
					T1.add(x2+1,y1-1,val);
					T1.add(X,y1-1,-val);
					T1.add(x1-1,y2,-val);
					T1.add(x2+1,y2,-val);
				}
				else {
					T1.add(X,y1,val);
					T1.add(x1-1,y2+1,val);
					T1.add(x2+1,y2+1,val);
					T1.add(X,y2+1,-val);
					T1.add(x1-1,y1,-val);
					T1.add(x2+1,y1,-val);
				}
			}
			else if(x1<X&&y1<Y) {
				T1.add(x2,y2,val);
				T1.add(x1-1,y1-1,val);
				T1.add(x1-1,y2,-val);
				T1.add(x2,y1-1,-val);
			}
			else if(x1<X&&y1>Y) {
				T1.add(x2,y1,val);
				T1.add(x1-1,y2+1,val);
				T1.add(x1-1,y1,-val);
				T1.add(x2,y2+1,-val);
			}
			else if(x1>X&&y1<Y) {
				T1.add(x1,y2,val);
				T1.add(x2+1,y1-1,val);
				T1.add(x1,y1-1,-val);
				T1.add(x2+1,y2,-val);
			}
			else if(x1>X&&y1>Y) {
				T1.add(x1,y1,val);
				T1.add(x2+1,y2+1,val);
				T1.add(x1,y2+1,-val);
				T1.add(x2+1,y1,-val);
			}
		}
	}
	return 0;
}

递归版代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;

const int maxn=5e5+5;

int n,m,X,Y,T;
ll a[maxn],b[maxn];

ll read() {
    ll x=0,f=1;char ch=getchar();
    for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    return x*f;
}

ll gcd(ll a,ll b) {
    if(!b)return abs(a);
    return gcd(b,a%b);
}

struct segment_tree_y {
    int tot;
    ll val[maxn<<2];
    int ls[maxn<<2],rs[maxn<<2];

    void build(int &p,int l,int r,int x) {
        p=++tot;
        if(l==r) {val[p]=a[(x-1)*m+l];return;}
        int mid=(l+r)>>1;
        build(ls[p],l,mid,x);
        build(rs[p],mid+1,r,x);
        val[p]=gcd(val[ls[p]],val[rs[p]]);
    }

    void update(int &p1,int p2,int p3,int l,int r) {
        p1=++tot;
        if(l==r) {val[p1]=gcd(val[p2],val[p3]);return;}
        int mid=(l+r)>>1;
        update(ls[p1],ls[p2],ls[p3],l,mid);
        update(rs[p1],rs[p2],rs[p3],mid+1,r);
        val[p1]=gcd(val[ls[p1]],val[rs[p1]]);
    }

    ll query(int p,int l,int r,int L,int R) {
        if(L<=l&&r<=R)return val[p];
        int mid=(l+r)>>1;ll res=0;
        if(L<=mid)res=query(ls[p],l,mid,L,R);
        if(R>mid)res=gcd(res,query(rs[p],mid+1,r,L,R));
        return res;
    }

    void add(int p,int l,int r,int pos,ll v) {
        if(l==r) {val[p]+=v;return;}
        int mid=(l+r)>>1;
        if(pos<=mid)add(ls[p],l,mid,pos,v);
        else add(rs[p],mid+1,r,pos,v);
        val[p]=gcd(val[ls[p]],val[rs[p]]);
    }

    void change(int p,int l,int r,int pos,ll v) {
        if(l==r) {val[p]=v;return;}
        int mid=(l+r)>>1;
        if(pos<=mid)change(ls[p],l,mid,pos,v);
        else change(rs[p],mid+1,r,pos,v);
        val[p]=gcd(val[ls[p]],val[rs[p]]);
    }
}T2;

struct segment_tree_x {
    int rt[maxn<<2];

    void build(int p,int l,int r) {
        if(l==r) {T2.build(rt[p],1,m,l);return;}
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
        T2.update(rt[p],rt[p<<1],rt[p<<1|1],1,m);
    }

    ll query(int p,int l,int r,int x1,int x2,int y1,int y2) {
        if(x1<=l&&r<=x2)return T2.query(rt[p],1,m,y1,y2);
        int mid=(l+r)>>1;ll res=0;
        if(x1<=mid)res=query(p<<1,l,mid,x1,x2,y1,y2);
        if(x2>mid)res=gcd(res,query(p<<1|1,mid+1,r,x1,x2,y1,y2));
        return res;
    }

    void add(int p,int l,int r,int x,int y,ll v) {
        if(x<1||x>n||y<1||y>m)return;
        if(l==r) {T2.add(rt[p],1,m,y,v);return;}
        int mid=(l+r)>>1;
        if(x<=mid)add(p<<1,l,mid,x,y,v);
        else add(p<<1|1,mid+1,r,x,y,v);
        ll lv=T2.query(rt[p<<1],1,m,y,y);
        ll rv=T2.query(rt[p<<1|1],1,m,y,y);
        T2.change(rt[p],1,m,y,gcd(lv,rv));
    }
}T1;

int main() {
    n=read(),m=read(),X=read(),Y=read(),T=read();
    for(int i=1;i<=n*m;i++)a[i]=read();
    for(int i=1;i<=n*m;i++) {
        int pos=(i-1)%m+1;
        if(pos<Y)b[i]=a[i]-a[i+1];
        else if(pos>Y)b[i]=a[i]-a[i-1];
        else b[i]=a[i];
    }
    for(int i=1;i<=n*m;i++) {
        int pos=(i-1)/m+1;
        if(pos<X)a[i]=b[i]-b[i+m];
        else if(pos>X)a[i]=b[i]-b[i-m];
        else a[i]=b[i];
    }
    T1.build(1,1,n);
    while(T--) {
        int opt=read(),x1=read(),y1=read(),x2=read(),y2=read();
        if(!opt) {
            x1=X-x1,x2=X+x2,y1=Y-y1,y2=Y+y2;
            printf("%lld
",T1.query(1,1,n,x1,x2,y1,y2));
        }
        if(opt) {
            ll val=read();
            if(x1<=X&&x2>=X&&y1<=Y&&y2>=Y) {
                T1.add(1,1,n,X,Y,val);
                T1.add(1,1,n,x1-1,y1-1,val);
                T1.add(1,1,n,x1-1,y2+1,val);
                T1.add(1,1,n,x2+1,y1-1,val);
                T1.add(1,1,n,x2+1,y2+1,val);
                T1.add(1,1,n,x1-1,Y,-val);
                T1.add(1,1,n,x2+1,Y,-val);
                T1.add(1,1,n,X,y1-1,-val);
                T1.add(1,1,n,X,y2+1,-val);
            }
            else if(y1<=Y&&y2>=Y) {
                if(x1<X) {
                    T1.add(1,1,n,x2,Y,val);
                    T1.add(1,1,n,x1-1,y1-1,val);
                    T1.add(1,1,n,x1-1,y2+1,val);
                    T1.add(1,1,n,x1-1,Y,-val);
                    T1.add(1,1,n,x2,y1-1,-val);
                    T1.add(1,1,n,x2,y2+1,-val);
                }
                else {
                    T1.add(1,1,n,x1,Y,val);
                    T1.add(1,1,n,x2+1,y1-1,val);
                    T1.add(1,1,n,x2+1,y2+1,val);
                    T1.add(1,1,n,x2+1,Y,-val);
                    T1.add(1,1,n,x1,y1-1,-val);
                    T1.add(1,1,n,x1,y2+1,-val);
                }
            }
            else if(x1<=X&&x2>=X) {
                if(y1<Y) {
                    T1.add(1,1,n,X,y2,val);
                    T1.add(1,1,n,x1-1,y1-1,val);
                    T1.add(1,1,n,x2+1,y1-1,val);
                    T1.add(1,1,n,X,y1-1,-val);
                    T1.add(1,1,n,x1-1,y2,-val);
                    T1.add(1,1,n,x2+1,y2,-val);
                }
                else {
                    T1.add(1,1,n,X,y1,val);
                    T1.add(1,1,n,x1-1,y2+1,val);
                    T1.add(1,1,n,x2+1,y2+1,val);
                    T1.add(1,1,n,X,y2+1,-val);
                    T1.add(1,1,n,x1-1,y1,-val);
                    T1.add(1,1,n,x2+1,y1,-val);
                }
            }
            else if(x1<X&&y1<Y) {
                T1.add(1,1,n,x2,y2,val);
                T1.add(1,1,n,x1-1,y1-1,val);
                T1.add(1,1,n,x1-1,y2,-val);
                T1.add(1,1,n,x2,y1-1,-val);
            }
            else if(x1<X&&y1>Y) {
                T1.add(1,1,n,x2,y1,val);
                T1.add(1,1,n,x1-1,y2+1,val);
                T1.add(1,1,n,x1-1,y1,-val);
                T1.add(1,1,n,x2,y2+1,-val);
            }
            else if(x1>X&&y1<Y) {
                T1.add(1,1,n,x1,y2,val);
                T1.add(1,1,n,x2+1,y1-1,val);
                T1.add(1,1,n,x1,y1-1,-val);
                T1.add(1,1,n,x2+1,y2,-val);
            }
            else if(x1>X&&y1>Y) {
                T1.add(1,1,n,x1,y1,val);
                T1.add(1,1,n,x2+1,y2+1,val);
                T1.add(1,1,n,x1,y2+1,-val);
                T1.add(1,1,n,x2+1,y1,-val);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AKMer/p/10211209.html