cf 341D lahub and xors

题目大意

给定初始值为(0)(n*n)矩阵
两种操作

  1. 矩形内异或一个值
  2. 求矩阵内异或和
    (nle 1000)

分析

二维线段树标记不下传貌似直接可做
有没有更简便的方法?
考虑异或的特性
我们修改((u,v)-(x,y)时(ule x,vle y))
修改((u,v))((x+1,y+1))((x+1,v))((u,y+1))这四个单点的值(a(x,y))

然后考虑我们只询问单点(val(x,y))
那么我们只需要计算$$igotimes_{i=1}xigotimes_{j=1}y a(x,y)$$

然后再考虑我们询问矩形((u,v)-(x,y))
首先差分成四个形如((1,1)-(X,Y))的询问,然后写下式子找规律

[egin{aligned} &igotimes_{i=1}^Xigotimes_{j=1}^Y val(i,j)\ =&igotimes_{i=1}^Xigotimes_{j=1}^Y igotimes_{x=1}^iigotimes_{y=1}^j a(x,y)\ =&igotimes_{x=1}^Xigotimes_{y=1}^Yleft(igotimes_{i=1}^{X-x+1}~igotimes_{j=1}^{Y-y+1}a(x,y) ight)\ =&igotimes_{x=1}^Xigotimes_{y=1}^Y [x,X奇偶同][y,Y奇偶同] a(x,y) end{aligned} ]

按(x,y)的奇偶性分成四个树状数组维护
可以发现任意两个树状数组没有公共点

注意我们把val化成了a
这样我们就只需要单点修改四个位置(修改到对应树状数组里)
然后询问的时候到(X,Y)奇偶性对应的树状数组里查询即可

solution

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
using namespace std;
const int M=1e3+7;
typedef long long LL;
 
inline int ri(){
    int x=0;bool f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    for(;isdigit(c);c=getchar()) x=x*10+c-48;
    return f?x:-x;
}
 
inline LL rl(){
    LL x=0;bool f=1;char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
    for(;isdigit(c);c=getchar()) x=x*10+c-48;
    return f?x:-x;
}
 
int n,m;
 
struct Bit{
    int c[M][M];
    Bit(){memset(c,0,sizeof c);}
    inline int lb(int x){return x&-x;}
    inline void add(int x,int y,LL d){
        int i,j;
        if(x==0||y==0) return;
        for(i=x;i<=n;i+=lb(i))
        for(j=y;j<=n;j+=lb(j)) c[i][j]^=d;
    }
    inline LL sum(int x,int y){
        int i,j; LL res=0;
        for(i=x;i>0;i-=lb(i))
        for(j=y;j>0;j-=lb(j)) res^=c[i][j];
        return res;
    }
}C[2][2];
 
inline int id(int x){return (x+1)>>1;}
 
LL get(int x,int y){
    return C[x&1][y&1].sum(id(x),id(y));
}
 
LL get(int u,int v,int x,int y){
    return get(x,y)^get(u-1,v-1)^get(x,v-1)^get(u-1,y);
}
 
void add(int x,int y,LL d){
    C[x&1][y&1].add(id(x),id(y),d);
}
 
void add(int u,int v,int x,int y,LL d){
    add(x+1,y+1,d); add(u,v,d); add(x+1,v,d); add(u,y+1,d);
}
 
int main(){
 
    int i,kd,u,v,x,y; LL d;
    n=ri(),m=ri();
 
    while(m--){
        kd=ri(),u=ri(),v=ri(),x=ri(),y=ri();
        if(kd==1) printf("%lld
",get(u,v,x,y));
        else{
            d=rl();//
            add(u,v,x,y,d);
        }
    }
 
    return 0;
}
原文地址:https://www.cnblogs.com/acha/p/7153573.html