zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    SPOJ AMR12B 720
    OUC_TeamTraining_#1 720
    Mac下安装必须软件
    spawn命令和expect
    python基础
    AndroidManifest.xml详解
    Ubuntu系统连接Android真机调试
    Android Studio 快捷键
    linux 解压/压缩命令
    sadasd
  • 原文地址:https://www.cnblogs.com/AKMer/p/10211209.html
Copyright © 2011-2022 走看看