CodeForces 341D

来源:互联网 发布:单片机原理及应用 编辑:程序博客网 时间:2024/06/05 11:50

题目大意:

   两种操作:

       Query(x0,y0,x1,y1) 将以(x0,y0)与(x1,y1)为顶点的矩形区域^val

       Update(x0,y0,x1,y1)将以(x0,y0)与(x1,y1)为顶点的矩形区域求^和

解决方法:

   先考虑一维的情况,如果现在不是在二维的情况,现在是在一维的情况,我们应该怎么做呢?

   建立一个二维树状数组,对于修改操作[x,y]我们执行两种操作,第一种add(x,v),第二种add(y+1,v) 但是现在是^,而不是相加,所以呢,我们就建立两个树状数组,如果x是奇数这修改第一个树状数组,否则修改第二个树状数组。因为如果处于x与y之间是,判断与x的奇偶性如果相同就为1,否者就为0,而查询的时候我们也正是这样,如果x是奇数,修改第一个,查询奇数项也是查询第一个,当询问大于y的时候,如果x与y+1奇偶性相同,一共修改偶数项,修改在同一个树状数组中,对后面没有影响。

    现在扩展到二维,也是一样的只不过现在是建立4个树状数组而已。

我的代码:

#include <iostream>#include <cstring>#include <cstdio>using namespace std;long long tree[2][2][1200][1200];int n,m;int add(int x,int y,int v){  for (int i=x;i<=n;i+=i&(-i))    for (int j=y;j<=n;j+=j&(-j))      tree[x&1][y&1][i][j]^=v;  return 0;}long long sum(int x,int y){  long long ans=0;  for (int i=x;i>0;i-=i&(-i))    for (int j=y;j>0;j-=j&(-j))      ans^=tree[x&1][y&1][i][j];  return ans;}int main(){  //freopen("test.in","r",stdin);  while (~scanf("%d%d",&n,&m)){    for (int i=1;i<=m;i++){        int op;scanf("%d",&op);        int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);        if (op==2){            long long val;cin>>val;            add(x2+1,y2+1,val);            add(x1,y2+1,val);            add(x2+1,y1,val);            add(x1,y1,val);        }        else {            long long ans=0;            ans^=sum(x2,y2);            if (x1>1) ans^=sum(x1-1,y2);            if (y1>1) ans^=sum(x2,y1-1);            if (x1>1&&y1>1) ans^=sum(x1-1,y1-1);            cout<<ans<<endl;        }    }  }  return 0;}


0 0
原创粉丝点击