Codeforces 869E. The Untended Antiquity (二维Fenwick,Hash)

Codeforces 869E. The Untended Antiquity

题意:

在一张mxn的格子纸上,进行q次操作:
1,指定一个矩形将它用栅栏围起来。
2,撤掉一个已有的栅栏。
3,询问指定两点之间是否连通(即能否从其中一点不翻越栅栏走到另一点)

思路:

对于操作1,将给定的矩形哈希成一个数(可对点坐标进行进制哈希),对整个矩形所覆盖的点都累加上这个数;
对于操作2,则逆着把操作1的影响抵消掉;
对于操作3,看一下两点的值是否相同(相同表示他们被相同的矩形们所覆盖)。
至于每次矩形内的所有点的修改操作以及单点查值,使用二维树状数组来维护,用到了差分思想,维护的是差分数组,则单点查询即求差分数组的前缀和。具体可见代码,在图上画一画,不难理解

代码:

#include<bits/stdc++.h>
#define de(x) cout<<#x<<" = "<<x<<"\n"
#define dd(x) cout<<#x<<" = "<<x<<" "
#define sz(x) int(x.size())
#define All(x) x.begin(),x.end()
#define fi first
#define se second
#define pb push_back
#define mp make_pair
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> P;
typedef priority_queue<int> BQ;
typedef priority_queue<int,vector<int>,greater<int> > SQ;
const int maxn=3e3+10,INF=0x3f3f3f3f;
ll fw[maxn][maxn];
void add(int x,int y,ll c)
{
    for (int i=x;i<maxn;i+=i&-i)
        for (int j=y;j<maxn;j+=j&-j)
            fw[i][j]+=c;
}
ll qry(int x,int y)
{
    ll res=0;
    for (int i=x;i;i-=i&-i)
        for (int j=y;j;j-=j&-j)
            res+=fw[i][j];
    return res;
}
ll seed=2333;
inline ll Hash(int a,int b,int c,int d)
{
    return a*seed*seed*seed+b*seed*seed+c*seed+d;
}
int main()
{
    int n,m,q;
    cin>>n>>m>>q;
    for (int i=0;i<q;++i)
    {
        int op,x1,y1,x2,y2;
        scanf("%d%d%d%d%d",&op,&x1,&y1,&x2,&y2);
        if (op==3)
        {
            if (qry(x1,y1)==qry(x2,y2))
                printf("Yes\n");
            else
                printf("No\n");
        }
        else
        {
            ll hs=Hash(x1,y1,x2,y2);
            if (op==2)
                hs=-hs;
            add(x1,y1,hs);
            add(x2+1,y2+1,hs);
            add(x1,y2+1,-hs);
            add(x2+1,y1,-hs);
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/orangee/p/9992308.html