[HASH,树状数组]CF869E

给定 n × m n\times m n×m 的空地,支持加围栏,去围栏,询问两点是否在连通块内。 n , m ≤ 2500 n,m\leq 2500 n,m2500 , q ≤ 1 0 5 q\leq 10^5 q105


题目中的询问两点是否连通相当于询问两点被包含的墙是否相等,以样例图为例

所以只用维护每个点被包含的区间即可。但 q q q 到达 1 0 5 10^5 105 级别,暴力比对肯定不行,用哈希的思想来维护。具体来说,对于每一个矩形维护一个哈希值,用树状数组维护前缀和单点修改,同时对于每次查询,只要对应值相等则为连通。(需要找一个不好卡的哈希算法,否则容易被卡)

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define lowbit(x) x&(-x)
map < pair< pii , pii > , int > M;
int n,m,q;
int a[2505][2505];

void add(int x,int y,int z)
{
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=m;j+=lowbit(j))
            a[i][j]+=z;
}
int get(int x,int y)
{
    int ans=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            ans+=a[i][j];
    return ans;
}

int main(){
	scanf("%d%d%d",&n,&m,&q);
	while(q--){
		int op,r1,c1,r2,c2;
		scanf("%d %d %d %d %d",&op,&r1,&c1,&r2,&c2);
		int x=r1*1327+c1*382-r2+c2*c2;
		if(op==1){
			add(r1,c1,x);add(r2+1,c2+1,x);
			add(r2+1,c1,-x);add(r1,c2+1,-x);
		}
		else if(op==2){
			x=-x;
			add(r1,c1,x);add(r2+1,c2+1,x);
			add(r2+1,c1,-x);add(r1,c2+1,-x);
		}
		else{
			int v1=get(r1,c1);
			int v2=get(r2,c2);
			printf("%s\n",(v1==v2)?"Yes":"No");
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值