zoukankan      html  css  js  c++  java
  • 【LOJ】#2672. 「NOI2012」魔幻棋盘

    题解

    代码7.1KB,人傻代码长
    恶心死我了这代码真的把我写恶心了= =

    想一想就知道这个东西……维护到中心的差分,然后用二维线段树维护一下矩形的gcd

    嗯,我说完了,你写吧。

    首先这个二维线段树的单点修改啊,要把第一维遍历过的节点也修改了,还不能直接修改,需要把第一维的左右子树里套的线段树拿出来合并

    然后这个差分啊,我为了好搞一点,拆成了9个矩阵,也就是
    中心,中心上方,中心下方,中心左方,中心右方,左上,右上,左下,右下
    每次和矩形取一个交集

    给中心左右的矩形加的时候需要给这个矩形的上下都差分上
    给中心的方块加的时候需要给这个矩形的四个角也差分上

    算了我讲不明白了,也不想画图了

    de了好长时间的bug,颓颓颓颓颓

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 500005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 - '0' + c;
    	c = getchar();
        }
        res = res * f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    
    int N,M,X,Y,T,Rt,Ncnt,tot;
    int64 D[MAXN],V,A[MAXN],num[MAXN];
    struct Matrix {
        int X1,X2,Y1,Y2;
    }MK[15];
    struct node {
        int lc,rc,rt;
        int64 G;
    }tr[MAXN * 70];
    int64 gcd(int64 a,int64 b) {
        return b == 0 ? a : gcd(b,a % b);
    }
    int c(int x,int y) {
        return (x - 1) * M + y;
    }
    
    void update(int u) {
        tr[u].G = gcd(abs(tr[tr[u].lc].G),abs(tr[tr[u].rc].G));
    }
    void build(int& u,int t,int L,int R) {
        u = ++Ncnt;
        if(L == R) {
    	tr[u].G = D[c(t,L)];
    	return;
        }
        int mid = (L + R) >> 1;
        build(tr[u].lc,t,L,mid);
        build(tr[u].rc,t,mid + 1,R);
        update(u);
    }
    void Union(int &u,int Lu,int Ru,int L,int R) {
        u = ++Ncnt;
        if(L == R) {
    	tr[u].G = gcd(abs(tr[Lu].G),abs(tr[Ru].G));
    	return;
        }
        int mid = (L + R) >> 1;
        Union(tr[u].lc,tr[Lu].lc,tr[Ru].lc,L,mid);
        Union(tr[u].rc,tr[Lu].rc,tr[Ru].rc,mid + 1,R);
        update(u);
    }
    void Build(int &u,int L,int R) {
        u = ++Ncnt;
        if(L == R) {
    	build(tr[u].rt,L,1,M);
    	return;
        }
        int mid = (L + R) >> 1;
        Build(tr[u].lc,L,mid);
        Build(tr[u].rc,mid + 1,R);
        Union(tr[u].rt,tr[tr[u].lc].rt,tr[tr[u].rc].rt,1,M);
    }
    void modify(int u,int L,int R,int p,int64 v) {
        if(L == R) {tr[u].G += v;return;}
        int mid = (L + R) >> 1;
        if(p <= mid) modify(tr[u].lc,L,mid,p,v);
        else modify(tr[u].rc,mid + 1,R,p,v);
        update(u);
    }
    void Union_modify(int u,int Lu,int Ru,int L,int R,int p) {
        if(L == R) {
    	tr[u].G = gcd(abs(tr[Lu].G),abs(tr[Ru].G));
    	return;
        }
        int mid = (L + R) >> 1;
        if(p <= mid) Union_modify(tr[u].lc,tr[Lu].lc,tr[Ru].lc,L,mid,p);
        else Union_modify(tr[u].rc,tr[Lu].rc,tr[Ru].rc,mid + 1,R,p);
        update(u);
    }
    void Modify(int u,int L,int R,int x,int y,int64 v) {
        
        if(L == R) {modify(tr[u].rt,1,M,y,v);return;}
        int mid = (L + R) >> 1;
        if(x <= mid) Modify(tr[u].lc,L,mid,x,y,v);
        else Modify(tr[u].rc,mid + 1,R,x,y,v);
        Union_modify(tr[u].rt,tr[tr[u].lc].rt,tr[tr[u].rc].rt,1,M,y);
        return;
    }
    int64 query(int u,int L,int R,int ql,int qr) {
        if(L == ql && R == qr) return abs(tr[u].G);
        int mid = (L + R) >> 1;
        if(qr <= mid) return query(tr[u].lc,L,mid,ql,qr);
        else if(ql > mid) return query(tr[u].rc,mid + 1,R,ql,qr);
        else return gcd(query(tr[u].lc,L,mid,ql,mid),query(tr[u].rc,mid + 1,R,mid + 1,qr));
    }
    int64 Query(int u,int L,int R,Matrix t) {
        if(L == t.X1 && R == t.X2) return query(tr[u].rt,1,M,t.Y1,t.Y2);
        int mid = (L + R) >> 1;
        if(t.X2 <= mid) return Query(tr[u].lc,L,mid,t);
        else if(t.X1 > mid) return Query(tr[u].rc,mid + 1,R,t);
        else return gcd(Query(tr[u].lc,L,mid,(Matrix){t.X1,mid,t.Y1,t.Y2}),
    		    Query(tr[u].rc,mid + 1,R,(Matrix){mid + 1,t.X2,t.Y1,t.Y2}));
    }
    void Init() {
        read(N);read(M);read(X);read(Y);read(T);
        for(int i = 1 ; i <= N ; ++i) {
    	for(int j = 1 ; j <= M ; ++j) {
    	    read(D[c(i,j)]);A[c(i,j)] = D[c(i,j)];
    	}
        }
        V = D[c(X,Y)];
        for(int i = 1 ; i <= N ; ++i) {
    	for(int j = 1 ; j <= Y - 1 ; ++j) {
    	    D[c(i,j)] = D[c(i,j)] - D[c(i,j + 1)];
    	}
    	for(int j = M ; j >= Y + 1 ; --j) {
    	    D[c(i,j)] = D[c(i,j)] - D[c(i,j - 1)];
    	}
        }
        for(int j = 1 ; j <= M ; ++j) {
    	for(int i = 1 ; i <= X - 1 ; ++i) {
    	    D[c(i,j)] = D[c(i,j)] - D[c(i + 1,j)];
    	}
    	for(int i = N ; i >= X + 1 ; --i) {
    	    D[c(i,j)] = D[c(i,j)] - D[c(i - 1,j)];
    	}
        }
        Build(Rt,1,N);
        MK[++tot] = (Matrix){X,X,1,Y - 1};
        MK[++tot] = (Matrix){X,X,Y + 1,M};
        MK[++tot] = (Matrix){1,X - 1,Y,Y};
        MK[++tot] = (Matrix){X + 1,N,Y,Y};
        MK[++tot] = (Matrix){1,X - 1,1,Y - 1};
        MK[++tot] = (Matrix){1,X - 1,Y + 1,M};
        MK[++tot] = (Matrix){X + 1,N,1,Y - 1};
        MK[++tot] = (Matrix){X + 1,N,Y + 1,M};
    }
    int64 Calc(Matrix a,Matrix b) {
        Matrix c;
        c.X1 = max(a.X1,b.X1);c.X2 = min(a.X2,b.X2);
        c.Y1 = max(a.Y1,b.Y1);c.Y2 = min(a.Y2,b.Y2);
        if(c.X1 > c.X2 || c.Y1 > c.Y2) return 0;
        return Query(Rt,1,N,c);
    }
    void Add_pos(int x,int y,int64 v) {
        if(x < 1 || x > N || y < 1 || y > M) return;
        Modify(Rt,1,N,x,y,v);
        D[c(x,y)] += v;
    }
    void Add(Matrix a,Matrix b,int64 v) {
        Matrix c;
        c.X1 = max(a.X1,b.X1);c.X2 = min(a.X2,b.X2);
        c.Y1 = max(a.Y1,b.Y1);c.Y2 = min(a.Y2,b.Y2);
        if(c.X1 > c.X2 || c.Y1 > c.Y2) return; 
        if(c.X1 == X) {
    	if(c.Y1 <= Y) {
    	    Add_pos(c.X1,c.Y2,v);Add_pos(c.X1,c.Y1 - 1,-v);
    	    Add_pos(c.X1 - 1,c.Y1 - 1,v);Add_pos(c.X1 + 1,c.Y1 - 1,v);
    	    Add_pos(c.X1 - 1,c.Y2,-v);Add_pos(c.X1 + 1,c.Y2,-v);
    	}
    	else {
    	    Add_pos(c.X1,c.Y1,v);Add_pos(c.X1,c.Y2 + 1,-v);
    	    Add_pos(c.X1 - 1,c.Y2 + 1,v);Add_pos(c.X1 + 1,c.Y2 + 1,v);
    	    Add_pos(c.X1 - 1,c.Y1,-v);Add_pos(c.X1 + 1,c.Y1,-v);
    	}
        }
        else if(c.Y1 == Y) {
    	if(c.X1 <= X) {
    	    Add_pos(c.X2,c.Y1,v);Add_pos(c.X1 - 1,c.Y1,-v);
    	    Add_pos(c.X1 - 1,c.Y1 - 1,v);Add_pos(c.X1 - 1,c.Y1 + 1,v);
    	    Add_pos(c.X2,c.Y1 - 1,-v);Add_pos(c.X2,c.Y1 + 1,-v);
    	}
    	else {
    	    Add_pos(c.X1,c.Y1,v);Add_pos(c.X2 + 1,c.Y1,-v);
    	    Add_pos(c.X1,c.Y1 - 1,-v);Add_pos(c.X1,c.Y1 + 1,-v);
    	    Add_pos(c.X2 + 1,c.Y1 - 1,v);Add_pos(c.X2 + 1,c.Y1 + 1,v);
    	}
        }
        else if(c.X1 < X) {
    	if(c.Y1 < Y) {
    	    Add_pos(c.X2,c.Y2,v);Add_pos(c.X2,c.Y1 - 1,-v);
    	    Add_pos(c.X1 - 1,c.Y2,-v);Add_pos(c.X1 - 1,c.Y1 - 1,v);
    	}
    	else {
    	    Add_pos(c.X2,c.Y1,v);Add_pos(c.X1 - 1,c.Y1,-v);
    	    Add_pos(c.X2,c.Y2 + 1,-v);Add_pos(c.X1 - 1,c.Y2 + 1,v);
    	}
        }
        else {
    	if(c.Y1 < Y) {
    	    Add_pos(c.X1,c.Y2,v);Add_pos(c.X1,c.Y1 - 1,-v);
    	    Add_pos(c.X2 + 1,c.Y2,-v);Add_pos(c.X2 + 1,c.Y1 - 1,v);
    	}
    	else {
    	    Add_pos(c.X1,c.Y1,v);Add_pos(c.X1,c.Y2 + 1,-v);
    	    Add_pos(c.X2 + 1,c.Y1,-v);Add_pos(c.X2 + 1,c.Y2 + 1,v);
    	}
        }
    }
    
    void Solve() {
        int op,X1,X2,Y1,Y2;
        int64 c;
        while(T--) {
    	read(op);read(X1);read(Y1);read(X2);read(Y2);
    	Matrix t;
    	if(op == 0) {
    	    int64 res = V;
    	    t = (Matrix){X - X1,X + X2,Y - Y1,Y + Y2};
    	    for(int i = 1 ; i <= tot ; ++i) {
    		res = gcd(res,Calc(MK[i],t));
    	    }
    	    out(res);enter;
    	}
    	else {
    	    t = (Matrix){X1,X2,Y1,Y2};
    	    
    	    read(c);
    	    
    	    if(X1 <= X && X <= X2 && Y1 <= Y && Y <= Y2) {
    		V += c;
    		Add_pos(X,Y,c);
    		Add_pos(X - 1,Y,-c);
    		Add_pos(X + 1,Y,-c);
    		Add_pos(X,Y - 1,-c);
    		Add_pos(X,Y + 1,-c);
    		Add_pos(X - 1,Y - 1,c);
    		Add_pos(X - 1,Y + 1,c);
    		Add_pos(X + 1,Y - 1,c);
    		Add_pos(X + 1,Y + 1,c);
    	    }
    	    for(int i = 1 ; i <= tot ; ++i) {
    		Add(MK[i],t,c);
    	    }
    	}
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    
  • 相关阅读:
    JAVA 多线程(3)
    JAVA 多线程(2)
    JAVA 多线程(1):synchronized
    阿里金服设置公钥-验证私钥
    linux (1): 启动
    新建项目虚拟环境及pycharm配置
    python创建udp服务端和客户端
    python创建tcp服务端和客户端
    python并发(阻塞、非阻塞、epoll)
    mongo基本操作
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9178227.html
Copyright © 2011-2022 走看看