zoukankan      html  css  js  c++  java
  • BZOJ2877 NOI2012魔幻棋盘(二维线段树)

      显然一个序列的gcd=gcd(其差分序列的gcd,序列中第一个数)。于是一维情况直接线段树维护差分序列即可。

      容易想到将该做法拓展到二维。于是考虑维护二维差分,查询时对差分矩阵求矩形的gcd,再对矩形的两个边界求一下原本的gcd即可。

      但这样大概需要三个二维线段树,空间可能不太够。由于查询区域是由一个给定点拓展的,可以改为以该点为中心建差分矩阵,这样剩下部分是一个十字形,可以直接一维线段树维护,就只需要一个二维线段树了。

      注意题面有锅,详见discuss,被坑了一年。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map> 
    using namespace std;
    #define ll long long
    #define N 500010
    #define pii pair<int,int>
    #define PII pair< pii , pii >
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    ll gcd(ll n,ll m){return m==0?n:gcd(m,n%m);}
    ll read()
    {
        ll x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,m,T,X,Y,root[2],cnt[2],CNT,ROOT;
    ll BIT[2][N];
    vector<ll> a[N];
    map<PII,int> id;
    struct data{int l,r,L,R;ll gcd;
    }tree[2][N<<1],TREE[N*20];
    void BIT_add(int op,int n,int x,ll y){while (x<=n) BIT[op][x]+=y,x+=x&-x;}
    ll BIT_query(int op,int x){ll s=0;while (x) s+=BIT[op][x],x-=x&-x;return s;}
    ll calc(int i,int j)
    {
        if (i<X&&j<Y) return a[i][j]-a[i+1][j]-a[i][j+1]+a[i+1][j+1];
        if (i<X&&j>Y) return a[i][j]-a[i+1][j]-a[i][j-1]+a[i+1][j-1];
        if (i>X&&j<Y) return a[i][j]-a[i-1][j]-a[i][j+1]+a[i-1][j+1];
        if (i>X&&j>Y) return a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
        return 0;
    }
    void add(int &k,int op,int l,int r,int x,ll p)
    {
        if (!k) k=++cnt[op];
        if (l==r) {tree[op][k].gcd+=p;return;}
        int mid=l+r>>1;
        if (x<=mid) add(tree[op][k].l,op,l,mid,x,p);
        else add(tree[op][k].r,op,mid+1,r,x,p);
        tree[op][k].gcd=gcd(tree[op][tree[op][k].l].gcd,tree[op][tree[op][k].r].gcd);
    }
    ll query(int k,int op,int l,int r,int x,int y)
    {
        if (x>y||!k) return 0; 
        if (l==x&&r==y) return tree[op][k].gcd;
        int mid=l+r>>1;
        if (y<=mid) return query(tree[op][k].l,op,l,mid,x,y);
        else if (x>mid) return query(tree[op][k].r,op,mid+1,r,x,y);
        else return gcd(query(tree[op][k].l,op,l,mid,x,mid),query(tree[op][k].r,op,mid+1,r,mid+1,y));
    }
    void BUILD(int &k,int l,int r,int x)
    {
        id[make_pair(make_pair(x,x),make_pair(l,r))]=k=++CNT;
        if (l==r) {TREE[k].gcd=calc(x,l);return;}
        int mid=l+r>>1;
        BUILD(TREE[k].l,l,mid,x);
        BUILD(TREE[k].r,mid+1,r,x);
        TREE[k].gcd=gcd(TREE[TREE[k].l].gcd,TREE[TREE[k].r].gcd);
    }
    void BUILD2(int &k,int l,int r,int u,int x,int y)
    {
        if (!k) id[make_pair(make_pair(l,r),make_pair(x,y))]=k=++CNT;
        TREE[k].L=id[make_pair(make_pair(l,u),make_pair(x,y))];
        TREE[k].R=id[make_pair(make_pair(u+1,r),make_pair(x,y))];
        TREE[k].gcd=gcd(TREE[TREE[k].L].gcd,TREE[TREE[k].R].gcd);
        if (x==y) return;
        int mid=x+y>>1;
        BUILD2(TREE[k].l,l,r,u,x,mid);
        BUILD2(TREE[k].r,l,r,u,mid+1,y);
    }
    void update(int k,int l,int r,int x)
    {
        TREE[k].gcd=gcd(TREE[TREE[k].L].gcd,TREE[TREE[k].R].gcd);
        if (l==r) return;
        int mid=l+r>>1;
        if (x<=mid) update(TREE[k].l,l,mid,x);
        else update(TREE[k].r,mid+1,r,x);
    }
    void build(int &k,int l,int r)
    {
        if (l==r) {BUILD(k,0,m+1,l);return;}
        id[make_pair(make_pair(l,r),make_pair(0,m+1))]=k=++CNT;
        int mid=l+r>>1;
        build(TREE[k].L,l,mid);
        build(TREE[k].R,mid+1,r);
        BUILD2(k,l,r,(l+r>>1),0,m+1);
    }
    void ADD(int &k,int l,int r,int x,ll p)
    {
        if (l==r) {TREE[k].gcd+=p;return;}
        int mid=l+r>>1;
        if (x<=mid) ADD(TREE[k].l,l,mid,x,p);
        else ADD(TREE[k].r,mid+1,r,x,p);
        TREE[k].gcd=gcd(TREE[TREE[k].l].gcd,TREE[TREE[k].r].gcd);
    }
    void Add(int k,int l,int r,int x,int y,ll p)
    {
        if (l==r) {ADD(k,0,m+1,y,p);return;}
        int mid=l+r>>1;
        if (x<=mid) Add(TREE[k].L,l,mid,x,y,p);
        else Add(TREE[k].R,mid+1,r,x,y,p);
        update(k,0,m+1,y);
    }
    ll QUERY(int k,int l,int r,int x,int y)
    {
        if (l==x&&r==y) return TREE[k].gcd;
        int mid=l+r>>1;
        if (y<=mid) return QUERY(TREE[k].l,l,mid,x,y);
        else if (x>mid) return QUERY(TREE[k].r,mid+1,r,x,y);
        else return gcd(QUERY(TREE[k].l,l,mid,x,mid),QUERY(TREE[k].r,mid+1,r,mid+1,y));
    }
    ll Query(int k,int l,int r,int xl,int xr,int yl,int yr)
    {
        if (xl>xr||yl>yr) return 0;
        if (l==xl&&r==xr) return QUERY(k,0,m+1,yl,yr);
        int mid=l+r>>1;
        if (xr<=mid) return Query(TREE[k].L,l,mid,xl,xr,yl,yr);
        else if (xl>mid) return Query(TREE[k].R,mid+1,r,xl,xr,yl,yr);
        else return gcd(Query(TREE[k].L,l,mid,xl,mid,yl,yr),Query(TREE[k].R,mid+1,r,mid+1,xr,yl,yr));
    }
    signed main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2877.in","r",stdin);
        freopen("bzoj2877.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),X=read(),Y=read(),T=read();
        for (int j=0;j<=m+1;j++) a[0].push_back(0);
        for (int i=1;i<=n;i++)
        {
            a[i].push_back(0);
            for (int j=1;j<=m;j++)
            a[i].push_back(read());
            a[i].push_back(0);
        }
        for (int j=0;j<=m+1;j++) a[n+1].push_back(0);
        build(ROOT,0,n+1);
        for (int i=1;i<=n;i++)
        BIT_add(0,n,i,a[i][Y]-a[i-1][Y]),add(root[0],0,1,n,i,a[i][Y]-a[i-1][Y]);
        for (int j=1;j<=m;j++)
        BIT_add(1,m,j,a[X][j]-a[X][j-1]),add(root[1],1,1,m,j,a[X][j]-a[X][j-1]);
        while (T--)
        {
            int op=read();
            if (op==0)
            {
                int up=read(),left=read(),down=read(),right=read();
                ll ans=gcd(BIT_query(0,X-up),query(root[0],0,1,n,X-up+1,X+down));
                ans=gcd(ans,gcd(BIT_query(1,Y-left),query(root[1],1,1,m,Y-left+1,Y+right)));
                ans=gcd(ans,Query(1,0,n+1,X-up,X-1,Y-left,Y-1));
                ans=gcd(ans,Query(1,0,n+1,X-up,X-1,Y+1,Y+right));
                ans=gcd(ans,Query(1,0,n+1,X+1,X+down,Y-left,Y-1));
                ans=gcd(ans,Query(1,0,n+1,X+1,X+down,Y+1,Y+right));
                printf(LL,abs(ans));
            }
            else
            {
                int xl=read(),yl=read(),xr=read(),yr=read();ll c=read();
                if (yl<=Y&&Y<=yr)
                {
                    BIT_add(0,n,xl,c),add(root[0],0,1,n,xl,c);
                    if (xr<n) BIT_add(0,n,xr+1,-c),add(root[0],0,1,n,xr+1,-c);
                }
                if (xl<=X&&X<=xr)
                {
                    BIT_add(1,m,yl,c),add(root[1],1,1,m,yl,c);
                    if (yr<m) BIT_add(1,m,yr+1,-c),add(root[1],1,1,m,yr+1,-c);
                }
                if (xl<=X&&yl<=Y)
                {
                    if (xr<X&&yr<Y) Add(1,0,n+1,xr,yr,c);
                    if (xr<X) Add(1,0,n+1,xr,yl-1,-c);
                    if (yr<Y) Add(1,0,n+1,xl-1,yr,-c);
                    Add(1,0,n+1,xl-1,yl-1,c);
                }
                if (xr>=X&&yl<=Y)
                {
                    if (xl>X&&yr<Y) Add(1,0,n+1,xl,yr,c);
                    if (xl>X) Add(1,0,n+1,xl,yl-1,-c);
                    if (yr<Y) Add(1,0,n+1,xr+1,yr,-c);
                    Add(1,0,n+1,xr+1,yl-1,c);
                }
                if (xl<=X&&yr>=Y)
                {
                    if (xr<X&&yl>Y) Add(1,0,n+1,xr,yl,c);
                    if (xr<X) Add(1,0,n+1,xr,yr+1,-c);
                    if (yl>Y) Add(1,0,n+1,xl-1,yl,-c);
                    Add(1,0,n+1,xl-1,yr+1,c);
                }
                if (xr>=X&&yr>=Y)
                {
                    if (xl>X&&yl>Y) Add(1,0,n+1,xl,yl,c);
                    if (xl>X) Add(1,0,n+1,xl,yr+1,-c);
                    if (yl>Y) Add(1,0,n+1,xr+1,yl,-c);
                    Add(1,0,n+1,xr+1,yr+1,c);
                }
            }
        }
        return 0;
    }
    
    

      

  • 相关阅读:
    不可或缺 Windows Native (15)
    不可或缺 Windows Native (14)
    不可或缺 Windows Native (13)
    不可或缺 Windows Native (12)
    不可或缺 Windows Native (11)
    不可或缺 Windows Native (10)
    不可或缺 Windows Native (9)
    不可或缺 Windows Native (8)
    不可或缺 Windows Native (7)
    不可或缺 Windows Native (6)
  • 原文地址:https://www.cnblogs.com/Gloid/p/10325550.html
Copyright © 2011-2022 走看看