The Untended Antiquity (二维树状数组 哈希)

题意:

3种操作

1 在左上角 (r1,c1)、右下角 (r2,c2) 的矩形框上设置围墙

2 把左上角 (r1,c1)、右下角 (r2,c2) 的矩形框上的围墙删掉

3 询问 (r1,c1) 能否不跨越围墙抵达 (r2,c2)

如图,两个红叉分别为 (r1,c1) (r2,c2), 粉色是它们围成的围墙,用二维树状数组维护这个网格:在棕色的四个点(r1,c1) (r1,c2+1) (r2+1,c1) (r2+1,c2+1)上打标记(单点更新一个随机值),对于每次询问,查寻(r1,c1)和(r2,c2)的二维前缀和是否相等,相等就表示它们在一个最小的矩形框内,可以互相抵达,否则不能。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2505,MOD=1e9+7;
ull rdm[N];
ll c[N][N];
int n,m,q;
void update(int _x,int _y,int val){
    for(int x=_x;x<=n;x+=x&-x) for(int y=_y;y<=m;y+=y&-y) c[x][y]+=val;
}
ll query(int _x,int _y){
    ll res=0;
    for(int x=_x;x;x-=x&-x) for(int y=_y;y;y-=y&-y) res+=c[x][y];
    return res;
}

int main(){
    srand(2333);
    for(int i=1;i<=2505;++i){
        rdm[i]=(rand()<<15)+rand();
        rdm[i]+=(rdm[i]<<30)+(rand()<<15)+rand();
        //cout<<"rdm["<<i<<"] "<<rdm[i]<<endl;
    }
    scanf("%d%d%d",&n,&m,&q);
    n++;m++;
    while(q--){
        int op,r1,c1,r2,c2;//左上 右下
        scanf("%d%d%d%d%d",&op,&r1,&c1,&r2,&c2);
        int hsh=(rdm[r1]*13+rdm[c1]*53+rdm[r2]*17+rdm[c2]*15)%MOD;//产生随机数
        if(op==1) update(r1,c1,hsh),update(r1,c2+1,-hsh),update(r2+1,c1,-hsh),update(r2+1,c2+1,hsh);else
        if(op==2) update(r1,c1,-hsh),update(r1,c2+1,hsh),update(r2+1,c1,hsh),update(r2+1,c2+1,-hsh);else
        if(query(r1,c1)==query(r2,c2)) puts("Yes");else puts("No");
    }
}

PS:Hash的方法学习一下

参考博客:

[哈希+差分] Codeforces 869E. The Untended Antiquity

扩展:树状数组+差分 处理 矩形覆盖 好像是个套路

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值