• CF341D-Iahub and Xors


    题目

    一个(n imes n)的零矩阵(a)(m)次操作:

    • (x_0 y_0 x_1 y_1 c),对(a[x][y],xin[x_0,x_1],yin[y_0,y_1])异或上一个数(c)
    • (x_0 y_0 x_1 y_1),询问这个子矩阵的异或和

    (nle 1000,mle 10^5,0le c<2^{62})

    分析

    树状数组的妙用!关键还是在异或的性质和处理矩阵的方法。

    首先考虑矩阵异或,单点查询,那么对于一个修改((x_0,y_0,x_1,y_1,c)),如果我们对((x_0,y_0),(x_0,y_1+1),(x_1+1,y_0),(x_1+1,y_1+1))都异或上(c),那么一个结论就是一个点((x,y))的值就是((1,1,x,y))的异或和。(画一画图就知道了)

    现在是询问子矩阵的异或和,显然首先转化为求任意的((1,1,x,y))的异或和。

    在之前那种修改方式下,一个点的点值就是((1,1,x,y))的异或和,那么要求((1,1,x,y))的异或和,我们就把这些异或和异或起来。

    考虑每个点的出现次数,我们会发现,对于一个点((x_0,y_0)),它在总异或中出现奇数次当且仅当((x-x_0+1)(y-y_0+1))为奇数。

    例如我们统计((1,1,3,4))的异或和的异或和,我们只用统计((1,2),(1,4),(3,2),(3,4))这几个点的值。

    于是对于每一种((x,y))的奇偶情况,我们开一个二维树状数组来进行单点修改,前缀异或和查询即可(二维树状数组就是一维树状数组的每个点都是一个树状数组)。

    代码

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long giant;
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const int maxn=1e3+2;
    int n,m;
    inline int lowbit(int x) {return x&-x;}
    struct BIT {
    	giant c[maxn][maxn];
    	void change(int x,int y,giant d) {
    		for (;x<=n+1;x+=lowbit(x)) for (int i=y;i<=n+1;i+=lowbit(i)) c[x][i]^=d;
    	}
    	giant query(int x,int y) {
    		giant ret=0;
    		for (;x;x-=lowbit(x)) for (int i=y;i;i-=lowbit(i)) ret^=c[x][i];
    		return ret;
    	}
    } t[2][2];
    giant get(int x,int y) {
    	giant ret=t[x&1][y&1].query((x+1)>>1,(y+1)>>1);
    }
    giant get(int x1,int y1,int x2,int y2) {
    	giant a=get(x1-1,y1-1);
    	giant b=get(x1-1,y2);
    	giant c=get(x2,y1-1);
    	giant d=get(x2,y2);
    	giant ret=a^b^c^d;
    	return ret;
    }
    void change(int x,int y,giant c) {
    	t[x&1][y&1].change((x+1)>>1,(y+1)>>1,c);
    }
    void change(int x1,int y1,int x2,int y2,giant c) {
    	change(x1,y1,c);
    	change(x1,y2+1,c);
    	change(x2+1,y1,c);
    	change(x2+1,y2+1,c);
    }
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	n=read(),m=read();
    	while (m--) {
    		int o=read(),x1=read(),y1=read(),x2=read(),y2=read();
    		giant c;
    		if (o==2) scanf("%lld",&c);
    		if (o==1) printf("%lld
    ",get(x1,y1,x2,y2)); else change(x1,y1,x2,y2,c);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Oracle在linux下的开机自启动(详细)转
    Xlib: connection to ":0.0" refused by server Xlib: No protocol specified解决方案
    java Comparable和Comaprator的对比
    java异常——RuntimeException和User Define Exception
    堆排序
    Java实现 蓝桥杯 算法提高 复数四则运算
    Java实现 蓝桥杯 算法训练 约数个数
    Java实现 蓝桥杯 算法训练 约数个数
    Java实现 蓝桥杯 算法提高 01背包
    Java实现 蓝桥杯 算法提高 判断名次
  • 原文地址:https://www.cnblogs.com/owenyu/p/7152495.html
Copyright © 2020-2023  润新知