codeforces869EThe Untended Antiquity(二维树状数组)

/*
二维树状数组+Hash
题意:
给一个地图(n,m) 三种操作:
1,在以(r1,c1)、(r2,c2)为对角的矩形四条边上添加障碍
2,消除以(r1,c1)、(r2,c2)为对角的矩形四条边上的障碍
3,判断(r1,c1)到(r2,c2)是否存在一条路径,不经过障碍

利用二维树状数组进行块更新,每次添加障碍时,用一个Hash值
如果两个点之间的Hash值是相同的,说明可以有路径不经过障碍
*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
typedef long long LL;
const int mod=10037;//用于Hash
const int maxn=2505;
map<pair<pair<int,int>,pair<int,int> >,LL>mp;//矩形的Hash值
int n,m,q;
LL tree[maxn][maxn];
int t,r1,c1,r2,c2;
//二维树状数组
int lowbit(int i)
{
    return i&(-i);
}
void add(int l,int r,LL v)
{
    for(int i=l;i<=n;i+=lowbit(i))
    {
        for(int j=r;j<=m;j+=lowbit(j))
        {
            tree[i][j]+=v;
        }
    }
}
LL get(int l,int r)
{
    LL ans=0;
    for(int i=l;i>=1;i-=lowbit(i))
    {
        for(int j=r;j>=1;j-=lowbit(j))
        {
            ans+=tree[i][j];
        }
    }
    return ans;
}
int main()
{
    while(~scanf("%d%d%d",&n,&m,&q))
    {
        mp.clear();
        LL Hash=1;//Hash值
        memset(tree,0,sizeof(tree));
        for(int i=0;i<q;i++)
        {
            scanf("%d%d%d%d%d",&t,&r1,&c1,&r2,&c2);
            if(t==1)
            {
                Hash*=mod;//保证每次添加障碍时,Hash值都不同
                mp[make_pair(make_pair(r1,c1),make_pair(r2,c2))]=Hash;//记录这个Hash值
                //题目保证障碍没有公共点
                add(r1,c1,Hash);
                add(r2+1,c2+1,Hash);
                add(r1,c2+1,-Hash);
                add(r2+1,c1,-Hash);
            }
            else if(t==2)
            {
                LL cnt=mp[make_pair(make_pair(r1,c1),make_pair(r2,c2))];
                add(r1,c1,-cnt);
                add(r2+1,c2+1,-cnt);
                add(r1,c2+1,cnt);
                add(r2+1,c1,cnt);
            }
            else if(t==3)
            {
                LL ans1=get(r1,c1);//获取此时的Hash值
                LL ans2=get(r2,c2);
                if(ans1==ans2)
                {
                    printf("Yes\n");
                }
                else
                {
                    printf("No\n");
                }
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值