2016ACM/ICPC Shengyang Online-1001 Resident Evil

本文介绍了一种使用二维树状数组解决特定类型问题的方法,该问题涉及在一个n*n的矩阵上进行操作,包括放置怪物及查询不同类型的怪物数量的奇偶性。文章通过实例详细解释了如何利用二维树状数组优化查询过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意和题解均参考:https://async.icpc-camp.org/d/560-2016-icpc

题意:有一个n*n的格子, 有50种怪物. 有m个操作, 每次操作会往一个矩形区域放怪物, 每个格子放相同数目的怪物, 或者查询当前50种怪物的奇偶性.

题解:把怪物个数的奇偶性用来表示就变成了一个裸二维树状数组, 考虑分成4个二维树状数组做, 具体参考Iahub and Xors. 需要注意, 同一种怪物在P操作里面会出现多次.

ps.统计(1,1,x,y)中xor和的时候,只有(x,y),(x-2,y),(x-4,y)等格子会对这个矩阵的和产生影响

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N=3010;
long long T[4][N][N];
int n,m;
int Get(int x,int y){
    int Res=0;
    if (x%2)Res+=1;
    if (y%2)Res+=2;
    return Res;
}
void Add(int x,int y,long long v)
{
    int Index=Get(x,y);
    for (int i=x;i<=n;i+=i&(-i))
        for (int j=y;j<=n;j+=j&(-j))
            T[Index][i][j]^=v;
}
long long Sum(int x,int y)
{
    long long Res=0;
    int Index=Get(x,y);
    for (int i=x;i;i-=i&(-i))
        for (int j=y;j;j-=j&(-j))
            Res^=T[Index][i][j];
    return Res;
}
int main()
{
    while (scanf("%d%d",&n,&m)!=EOF){
        memset(T,0,sizeof T);
        char str[10];int x0,y0,x1,y1,K;long long v;
        while (m--){
            v=0;
            scanf("%s",str);
            if (str[0]=='P'){
                scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&K);
                for (int i=1;i<=K;i++){
                    int A,B;scanf("%d%d",&A,&B);
                    if (B&1)v^=(1LL<<(A-1));
                }
                Add(x0,y0,v);
                Add(x1+1,y0,v);
                Add(x0,y1+1,v);
                Add(x1+1,y1+1,v);
            }else{
                scanf("%d%d%d%d",&x0,&y0,&x1,&y1);
                v^=Sum(x1,y1);
                v^=Sum(x1,y0-1);
                v^=Sum(x0-1,y1);
                v^=Sum(x0-1,y0-1);
                for (int i=1;i<50;i++)
                    printf("%d ",(v&(1LL<<(i-1)))?2:1);
                printf("%d \n",(v&(1LL<<(50-1)))?2:1);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值