HDU5892 Resident Evil(二维树状数组+状态压缩)

来源:互联网 发布:外国人羡慕中国淘宝 编辑:程序博客网 时间:2024/06/05 03:58

“`
Resident Evil

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 633 Accepted Submission(s): 145

Problem Description
The Umbrella Company has developed a new biochemical virus secretly. Lyon, a staff of the company, happened to find out the conspiracy and his company is now stopping him from discovering further evidence by releasing biochemical monster in his city (don’t ask me why the company is using this weird method).

The city can be described as an n*n grids. The Umbrella Company has 50 kinds of biochemical monster in total. The company will specify the type, quantity of biochemical monster and the rectangle area to put monster. For example, if the specified rectangle area has upper left corner (1, 1) and bottom right corner of (3, 3), and the company wishes to put 3 of A monster, 2 of B monster and 1 of C monster in it, then 3 of A monster, 2 of B monster and 1 of C monster is added to each and every grid inside the area.

However, Lyon risk his life of finding evidence by searching certain rectangle area. By doing this, all monsters inside the area would gather to him. He has two way of dealing with monster. If the number of a certain kind of monster is even, then he would choose to hide, otherwise withdraw.

Input
A line containing n and m (1<=n<=3000 1<=m<=100000). Representing the size of the city and the number of operations.

Then m lines of operation and there are only two kinds of operation.

Letter ‘P’ means to release monster, followed by 4 integers x1, y1, x2, y2 (1<=x1, y1, x2, y2<=n) , describing the upper left corner and bottom right corner of the area. Then an integer K(1<=K<=50), meaning there will be k pair of number (A, B) given next. A (1<=A<=50) indicates the kind of the monster and B (1<=b<=100000) indicates the number of this kind being added to this area.

Letter ‘Q’ represents the query operation, followed by 4 integers x1, y1, x2, y2 (1<=x1, y1, x2, y2<=n), describing the upper left corner and bottom right corner of the area.

Output
For every ‘Q’ operation. Print 50 number in a line, meaning the kind of action he would take for different kinds of monsters. 1 represents hiding and 2 represents withdrawing.

Sample Input
2 2
P 1 1 2 2 1 1 1
Q 1 1 1 1

Sample Output
2 1 1 1 1 1 ……..1 (one ‘2’ and forty-nine ‘1’)

Source
2016 ACM/ICPC Asia Regional Shenyang Online

Recommend
wange2014 | We have carefully selected several similar problems for you: 5932 5931 5930 5929 5928

```二维树状树状:这里涉及状态压缩:安利一篇介绍状态压缩相关的文章:

  传送门:状态压缩

```这道题的题意是:1.在以(x1,y1),(x2,y2)为端点的矩形区域内的每一个格子,放入k对(A,B)怪物,(B只A种类的怪物)2.统计在以(x1,y1),(x2,y2)为端点的矩形区域内,50种怪物的所对应的数量.这里我们就要用到了二维数组了。第一个操作涉及到了二维数组的区间更新,就是说我们要把对应矩阵区域内的所有格子加上对应数量的怪物.由于我们不需要知道对应的怪物的具体数量,只需要知道对应的怪物的数量是奇数还是偶数。所以我们这里可以用0,1来表示对应怪物的数量是偶数还是奇数,并且我们要用到位运算异或。在矩形区域内,我们如果加入的偶数只对应的怪物,在这区域内,无论怎么算偶数*偶数个格子(被添加到的格子)=偶数,偶数*奇数个格子=偶数,对应的异或值依旧没有变,所以我们不需要讨论加入的对应的怪物数量是偶数的情况。那么我们就要来讨论奇数的情况,由于奇数*偶数=奇数,奇数*奇数=奇数,所以怪物被添加到x+1,x+3,x+5...等格子是毫无影响的,只有被添加到x+2,x+4,x+6...等格子,该格子的值才会变化(y的情况也是一样的,控制被添加格子数的奇偶).所以我们就可以ll t[2][2][maxn][maxn]分别控制格子的奇数偶数.然后怪物呢,50种,我们就需要状态压缩了。1LL<<50,对应的2进制值表示该位怪物的数量的奇偶性。0000010000表示第5种怪物的数量是奇数,其余是偶数。
#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<cctype>#include<cmath>#include<ctime>#include<string>#include<stack>#include<deque>#include<queue>#include<list>#include<set>#include<map>#include<cstdio>#include<limits.h>#define MOD 1000000007#define fir first#define sec second#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)#define mes(x, m) memset(x, m, sizeof(x))#define Pii pair<int, int>#define Pll pair<ll, ll>#define INF 1e9+7#define Pi 4.0*atan(1.0)#define lowbit(x) (x&(-x))#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1typedef long long ll;typedef unsigned long long ull;const double eps = 1e-12;const int maxn = 3001;using namespace std;inline int read(){    int x(0),op(1);    char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')op=-1,ch=getchar();}    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();    return x*op;}//ji&ji==ji ji&ou=ouint N,Q;ll t[2][2][maxn][maxn];ll monster[50];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)){            t[x&1][y&1][i][j]^=val;        }    }}ll sum(int x,int y){    ll res=0;    for(int i=x;i>0;i-=lowbit(i)){        for(int j=y;j>0;j-=lowbit(j)){            res^=t[x&1][y&1][i][j];        }    }    return res;}int main(){  //  fin;    int x1,x2,y1,y2,k,m,n;    N=read(),Q=read();    char op[3];    mes(t,0);    while(Q--){        scanf("%s%d%d%d%d",op,&x1,&y1,&x2,&y2);        if(op[0]=='P'){            mes(monster,0);          //  k=read();            scanf("%d",&k);            while(k--){              // m=read(),n=read();                scanf("%d%d",&m,&n);                monster[--m]+=n;            }            ll t=0;            for(int i=0;i<50;++i){               if(monster[i]&1){                     t|=(1LL<<i); //第i位设置为1,即第(i+1)种怪物的数量为奇数               }            }            ++x2,++y2;            update(x1,y1,t); //区间更新            update(x2,y2,t);            update(x1,y2,t);            update(x2,y1,t);        }        else{            --x1,--y1;            ll t=sum(x1,y1)^sum(x2,y2)^sum(x1,y2)^sum(x2,y1); //求区间的异或值(由a^a=0,a^0=a,所以我们异或掉多出来矩形的部分也就是我们所求的区域的值(就像我们求(x,y)的值,求出来的是(1,1)->(x,y)区域的值,如果我们求特定部分矩形的面积,我们需要减掉多余部分的值,这里把多余部分的值直接异或掉就可以了。))            for(int i=0;i<50;++i){                if(t&(1LL<<i)){                    printf("2 ");                }                else{                    printf("1 ");                }            }            printf("\n");        }    }    return 0;}
0 0
原创粉丝点击