您的位置:首页 > 理论基础 > 计算机网络

hdu 5892 沈阳网络赛 二维树状数组+状态压缩

2017-05-15 09:43 483 查看
题目大意:有50种动物,给你n*n的矩阵,m次操作,P代表加入操作,在左上角 x1,y1 到右下角 x2,y2,的矩形范围内加入种类为x,数量为y的动物。

Q代表询问操作,在左上角 x1,y1 到右下角 x2,y2,对于1~50种动物,如果数量之和为偶数,输出1,否则输出2。

点1:涉及到二维的区间查询更新,应该是用树状数组,怎么更新呢。因为只用到奇偶性,所以 先猜想再一维上,如果普通的单点更新,如果是 50种动物 那么每种动物 都是 +=val。

然而在树状数组里面,树状数组的更新是往后的,求和是在前面。所以相当于 从x开始后面的点是按照奇数 偶数 次更新,如果是偶数次更新,结果不变,如果是奇数次更新,值才会改变。所以把x后面的数组划分成两个部分 [x&1][i]

这样就是二维的了。 加上y 变成四维。对于树状数组C[L..R],每个位置异或X的次数是奇、偶交错的的,而异或相同的一个数偶数次等于没异或,异或相同的一个数奇数次相当于异或一次。

就·好像你在1 2 3位置放相同数量的动物 那么 求 1,2 的和时 奇偶性不变。

还有就是位运算或者别的,ll和int的变化时,int都要强制转为ll

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
#define lowbit(x) (x)&(-x)
const int maxn=3010;
typedef long long ll;
ll b[2][2][maxn][maxn];
int n,m;
ll mo[55];
void update(int x,int y,ll val)
{
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]^=val;
}
}
}

ll sum(int x,int y)
{
ll sum=0;
for(int i=x;i>0;i-=lowbit(i))
{
for(int j=y;j>0;j-=lowbit(j))
{
sum^=b[x&1][y&1][i][j];
}
}
return sum;
}

int main(){
while(scanf("%d%d",&n,&m)!=EOF){
memset(b,0,sizeof(b));
while(m--)
{
char op;
int x1,y1,x2,y2;
scanf(" %c%d%d%d%d",&op,&x1,&y1,&x2,&y2);
if(op=='P')
{
memset(mo,0,sizeof(mo));
int k;
scanf("%d",&k);
int a,c;
for(int i=0;i<k;i++)
{
scanf("%d%d",&a,&c);
mo[--a]+=c;
}
ll t=0;
for(int i=0;i<50;i++)
if(mo[i]&1)
{
t|=(1LL<<i);//被这个坑了
}
x2++,y2++;
update(x1,y1,t);
update(x1,y2,t);
update(x2,y1,t);
update(x2,y2,t);
}
else
{
x1--,y1--;
ll res=0;
res^=sum(x1,y1);
res^=sum(x1,y2);
res^=sum(x2,y1);
res^=sum(x2,y2);
for(int i=0;i<50;i++)
{
if(res&(1LL<<i))
printf("2 ");
else printf("1 ");
}
printf("\n");
}

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: