HDU 5892 Resident Evil

题目链接:传送门

题目大意:有50种动物,给你n*n的矩阵,m次操作,P代表加入操作,在左上角 x1,y1 到右下角 x2,y2,的矩形范围内加入

     种类为x,数量为y的动物。

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

题目思路:树状数组 区间异或,区间查询。

/*--------------------------------------------------分割线-------------------------------------------------------------*/

以下均考虑树状数组维护异或值

我们首先要知道树状数组都是向后更新,向前查询的。

首先考虑简单的问题

如果要求一维空间,单点修改,区间查询,那这个就直接像普通树状数组那样,修改和查询时把+改成^就行了。

如果要求一维空间,区间修改,区间查询,这时候就不能像普通树状数组那么改了。不信可以试试。:)

  如果异或更新 [x,y] ^v

  我们知道这样一个性质,假如对于位置 x,那么x+1,x+3,x+7...这些位置上的值是不会被V影响的。

  因为更新时这些位置上的数异或V偶数次,值不会受影响。只有与 x 奇偶性相同的位置 x+2,x+4...才会被更新。

  因此,我们可以开个二维数组tree[2][maxn],只修改 x奇偶性对应的那一维,比如可以写成 x&1,偶数修改0,奇数修改1

  查询时对应奇偶性查询。

本题要求二维空间,区间修改,区间查询,那么扩展一下,开4个数组即可。

然后我们把对应的50种动物状态压缩 1<<50,开LL tree[4][3001][3001],这样不会爆空间。

然后对于加入的动物数量,首先不用去管面积,直接用给的数量值(因为 偶*奇==偶,偶*偶==偶)

所以只要加入偶数数量就不用管,因为数量永远是偶数,而初始值0也是偶数,也就是对答案没影响。

对于加入奇数的情况,就必须老老实实加入(奇*奇==奇,奇*偶==偶),面积会对奇数情况有影响。

之后只需按上诉方法异或即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <cstring>
 7 #include <stack>
 8 #include <cctype>
 9 #include <queue>
10 #include <string>
11 #include <vector>
12 #include <set>
13 #include <map>
14 #include <climits>
15 #define lson rt<<1,l,mid
16 #define rson rt<<1|1,mid+1,r
17 #define fi first
18 #define se second
19 #define ping(x,y) ((x-y)*(x-y))
20 #define mst(x,y) memset(x,y,sizeof(x))
21 #define mcp(x,y) memcpy(x,y,sizeof(y))
22 using namespace std;
23 #define gamma 0.5772156649015328606065120
24 #define mod 1000000007
25 #define inf 0x3f3f3f3f
26 #define N 1005050
27 #define maxn 3001
28 typedef pair<int,int> PII;
29 typedef long long LL;
30 
31 int n,m,k,x,y,v;
32 LL tree[2][2][3001][3001];
33 int x1,y1,x2,y2;
34 LL mon[50];
35 void add(int x,int y,LL v){
36     for(int i=x;i<=n;i+=(i&-i))
37     for(int j=y;j<=n;j+=(j&-j))
38         tree[x&1][y&1][i][j]^=v;
39 }
40 LL query(int x,int y){
41     LL res=0;
42     for(int i=x;i;i-=(i&-i))
43     for(int j=y;j;j-=(j&-j))
44         res^=tree[x&1][y&1][i][j];
45     return res;
46 }
47 int main(){
48     //freopen("in.txt","r",stdin);
49     int i,j,group;
50     char ch;
51     while(scanf("%d%d",&n,&m)!=EOF){
52         mst(tree,0);
53         while(m--){
54             scanf(" %c%d%d%d%d",&ch,&x1,&y1,&x2,&y2);
55             if(ch=='P'){
56                 mst(mon,0);
57                 scanf("%d",&k);
58                 while(k--){
59                     scanf("%d%d",&x,&y);
60                     --x;
61                     mon[x]+=y;
62                 }
63                 LL temp=0;
64                 for(i=0; i<50; ++i){
65                     if(mon[i]&1)
66                     temp|=(1ll<<i);
67                 }
68                 ++x2;++y2;
69                 add(x1,y1,temp);
70                 add(x2,y2,temp);
71                 add(x1,y2,temp);
72                 add(x2,y1,temp);
73             }
74             else{
75                 --x1,--y1;
76                 LL temp=query(x1,y1)^query(x2,y2)^query(x1,y2)^query(x2,y1);
77                 for(i=0;i<50;++i)
78                     if(temp&(1ll<<i))printf("2 ");
79                     else printf("1 ");
80                 printf("
");
81             }
82         }
83     }
84     return 0;
85 }

     

原文地址:https://www.cnblogs.com/Kurokey/p/5887157.html