Description
给出一个 n×n n × n 的矩阵,有 50 50 种动物,初始时矩阵每个位置都没有动物, m m 次操作,操作分两种
:在子矩阵 [x1,x2]×[y1,y2] [ x 1 , x 2 ] × [ y 1 , y 2 ] 的每个位置放 bi b i 个第 ai a i 种动物
Q x1 y1 x2 y2: Q x 1 y 1 x 2 y 2 : 查询子矩阵 [x1,x2]×[y1,y2] [ x 1 , x 2 ] × [ y 1 , y 2 ] 所有位置这 50 50 种动物数量之和的奇偶性
Input
第一行输入两个整数 n,m n , m 表示矩阵维数和查询数,之后 m m 行每行一组查询
Output
对于每组查询输出 50 50 个整数,第 i i 个整数表示子矩阵中第种动物数量之和的奇偶性(奇数输出 2 2 ,偶数输出)
Sample Input
2 2
P 1 1 2 2 1 1 1
Q 1 1 1 1
Sample Output
2 1 …. 1
Solution
把五十种动物的奇偶性用 50 50 位 01 01 压成一个状态,每次加入偶数的动物显然对答案没影响,加入奇数个动物等价于加入一个动物,子矩阵动物数量之和的奇偶性等价于每个位置该种动物数量奇偶性的异或和
首先看一维情况,即区间异或的操作和区间异或和的查询,由树状数组可以把这两种操作变成单点修改和前缀异或和查询,如果对区间 [L,R] [ L , R ] 进行异或 x x 的操作,考虑该次操作对前缀异或和的影响,显然如果 y y 和奇偶性相同那么影响为 x x ,否则影响为,而该区间异或 x x 的操作在实现时是对位置异或 x x ,并对位置异或 x x 以消除对后面值的影响,故如果单点修改位置为奇数,那么该次修改只对该位置及其之后的奇数位置的前缀异或和有影响,偶数同理,那么如果直接把普通的树状数组的加法改成异或显然是不对的,因为对于一个偶数位置的前缀和,其前面奇数位置的修改也会被统计到,为避免这种情况,再加一维表示修改查询位置的奇偶性,把奇偶性不同的修改查询位置分成两个树状数组分别处理
对于二维情况,只需对一维情况做推广,对子矩阵的修改变成对 (x1,y1),(x1,y2+1),(x2+1,y1),(x2+1,y2+1) ( x 1 , y 1 ) , ( x 1 , y 2 + 1 ) , ( x 2 + 1 , y 1 ) , ( x 2 + 1 , y 2 + 1 ) 四个顶点的修改,对该子矩阵的查询也变成对以这四个顶点为右下角, (1,1) ( 1 , 1 ) 位左上角的前缀子矩阵查询,每次修改点 (x,y) ( x , y ) 的值以及查询 [1,x]×[1,y] [ 1 , x ] × [ 1 , y ] 的前缀异或和时,要根据 x,y x , y 奇偶性的不同分到四个树状数组中分别处理
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
#define maxn 3210
int n,m;
ll f[55];
struct BIT
{
#define lowbit(x) (x&-x)
ll b[2][2][maxn][maxn];
void init()
{
memset(b,0,sizeof(b));
}
void update(int x,int y,ll v)
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
b[x&1][y&1][i][j]^=v;
}
ll query(int x,int y)
{
ll ans=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y;j;j-=lowbit(j))
ans^=b[x&1][y&1][i][j];
return ans;
}
}bit;
void Update(int x1,int y1,int x2,int y2,ll v)
{
bit.update(x2,y2,v);
bit.update(x1,y1,v);
bit.update(x1,y2,v);
bit.update(x2,y1,v);
}
void Query(int x1,int y1,int x2,int y2)
{
ll ans=bit.query(x2,y2)^bit.query(x1,y1)^bit.query(x1,y2)^bit.query(x2,y1);
for(int i=1;i<=50;i++)
if(ans&f[i])printf("2 ");
else printf("1 ");
printf("\n");
}
int main()
{
f[1]=2;
for(int i=2;i<=50;i++)f[i]=2ll*f[i-1];
while(~scanf("%d%d",&n,&m))
{
bit.init();
while(m--)
{
char op[11];
int x1,y1,x2,y2,k,kind,num;
ll temp;
scanf(" %s%d%d%d%d",op,&x1,&y1,&x2,&y2);
if(op[0]=='P')
{
scanf("%d",&k);
temp=0;
while(k--)
{
scanf("%d%d",&kind,&num);
if(num&1)temp^=f[kind];
}
Update(x1,y1,x2+1,y2+1,temp);
}
else Query(x1-1,y1-1,x2,y2);
}
}
return 0;
}