/*
codeforces 869e 二维树状数组维护
Author:lcy
Time:2017-10-18
在一个平面上可以有两种操作,添加矩形围墙以及删除矩形围墙,
题目保证围墙之前不会相交。
同时会有多组询问,给出两个点,判断能否相互抵达

怎么把围墙表示出来?
给出左上角的点(x1,y1),右下角的点(x2,y2),我们只需要
在以(x1,y1),(x2+1,y2+1)为对角的矩形周围建立围墙即可。
然后就需要运用技巧:在二维数组的(x1,y1),(x2+1,y2+1)的
位置加上一个值t,在(x1,y2+1),(x2+1,y1)的位置减去一个值t。
注意,不同墙的t值需要不同,由于每次给出对角的两点不同,
可以用这个性质去构造t值,以确保不同。

在查询的时候,分别计算两个点到原点的二维前缀和,
如果两个点不属于一个矩形,那么前缀和一定不相等。
如果相等,则意味着属于一个矩形,一定可以相互到达。
*/

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) ((x)&(-x))
const int MAXN=2505;
ll k[MAXN][MAXN],f[MAXN][MAXN];
int n,m,q;
void update(int x,int y,ll t){
    k[x][y]+=t;
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=m+1;j+=lowbit(j))
            f[i][j]+=t;
}
ll get_sum(int x,int y){
    ll ans=0;
    for(int i=x;i>=1;i-=lowbit(i))
        for(int j=y;j>=1;j-=lowbit(j))
            ans+=f[i][j];
    return ans;
}
void add(int x1,int y1,int x2,int y2,ll t){
    update(x1,y1,t);
    update(x2+1,y2+1,t);
    update(x1,y2+1,-t);
    update(x2+1,y1,-t);
}
ll get_hash(int x1,int y1,int x2,int y2){
    ll ans=0;
    ans=(ll)x1;
    ans=(ans*109ll+(ll)y1);
    ans=(ans*109ll+(ll)x2);
    ans=(ans*109ll+(ll)y2);
    return ans;
}
int main(){
    scanf("%d%d%d",&n,&m,&q);
    while(q--){
        int a,b,c,d,e;
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
        switch(a){
            case 3:
               puts(get_sum(b,c)==get_sum(d,e)?"Yes":"No"); 
               break;
            default:
               ll x,hs;
               x=a==1?1ll:-1ll;
               hs=get_hash(b,c,d,e);
               add(b,c,d,e,hs*x);
        }
    }
    return 0;
}
 posted on 2017-10-18 15:35  cylcy  阅读(118)  评论(0编辑  收藏  举报