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\n",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\n",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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值