[HDU 5892] Resident Evil (二维树状数组)

链接

HDU 5892


题意

沈阳网络赛A题。。。
给出一个n*n的矩阵,m组操作,每次操作可以向一个矩形范围内投掷多种怪兽(一共50种),每种若干只,每次操作也可以查询某个矩形范围内怪兽的奇偶性,每次输出50种怪兽的奇偶性。


题解

只关注怪兽的奇偶性,并且怪兽种类50只,那么每次投放的怪兽可以压缩在一个longlong变量内,就变成了二维树状数组的经典问题,区间异或问题。


题解
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long lint;
#define maxn (3030)
lint c[2][2][maxn][maxn];
inline int lowbit(int x) { return x&-x; }
void add(int x, int y, lint val, int n)
{
    for(int i = x; i <= n; i += lowbit(i))
    {
        for(int j = y; j <= n; j += lowbit(j))
        c[x&1][y&1][i][j] ^= val;
    }
}
lint get(int x, int y)
{
    lint o = 0;
    for(int i = x; i; i -= lowbit(i))
    {
        for(int j = y; j; j -= lowbit(j))
        o ^= c[x&1][y&1][i][j];
    }
    return o;
}
lint type[55];
lint f()
{
    int k, a, b;
    lint o = 0;
    scanf("%d", &k);
    while(k--)
    {
        scanf("%d%d", &a, &b);
        if(b % 2) o ^= type[a];
    }
    return o;
}
int main()
{
    lint mask = 1;
    for(int i = 1; i <= 50; i++)
    { type[i] = 0; type[i] |= mask; mask <<= 1; }

    int n, m;
    while(cin >> n >> m)
    {
        for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
        c[0][0][i][j] = c[0][1][i][j] = c[1][0][i][j] = c[1][1][i][j] = 0;
        char op[5];
        int x0, y0, x1, y1;
        lint g, o;
        while(m--)
        {
            scanf("%s%d%d%d%d", op, &x0, &y0, &x1, &y1);
            if(op[0] == 'P')
            {
                g = f();
                add(x0, y0, g, n);
                add(x0, y1 + 1, g, n);
                add(x1 + 1, y0, g, n);
                add(x1 + 1, y1 + 1, g, n);
            }
            else
            {
                o = 0;
                o ^= get(x1, y1);
                o ^= get(x0 - 1, y1);
                o ^= get(x1, y0 - 1);
                o ^= get(x0 - 1, y0 - 1);
                for(int i = 0; i < 50; i++)
                {
                    if(o & 1ll) putchar('2');
                    else putchar('1');
                    putchar(' ');
                    o >>= 1;
                }
                putchar('\n');
            }
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值