Codeforces #439 Div2 E

#439 Div2 E

题意

给出二维平面,有多个询问:

  1. 把某一区域围起来(围墙之间无交点)
  2. 移除某一区域的围墙(此时保证围墙一定存在)
  3. 选定两个位置问是否可以互相到达

分析

看起来很复杂,其实这道题限制颇多,实际并不用去寻找使得两个位置可以互相到达的路线,考虑二维树状数组维护某一点的状态,表示它被哪些矩形覆盖过,只要询问的两点被同样的矩形覆盖过,它们一定可以互相到达。对于覆盖的矩形,用一个随机数作为增加的值。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 2515;
ll f[MAXN][MAXN];

void update(int x, int y, ll z) {
    while(x < MAXN) {
        int j = y;
        while(j < MAXN) {
            f[x][j] += z;
            j += j & -j;
        }
        x += x & -x;
    }
}

ll query(int x, int y) {
    ll sum = 0;
    while(x) {
        int j = y;
        while(j) {
            sum += f[x][j];
            j -= j & -j;
        }
        x -= x & -x;
    }
    return sum;
}

map<array<int, 4>, ll> mp;

int main() {
    ios::sync_with_stdio(0); cin.tie(0);
    int n, m, q;
    cin >> n >> m >> q;
    while(q--) {
        int t, a, b, c, d;
        cin >> t >> a >> b >> c >> d;
        if(t == 1) {
            ll tmp = 1LL * rand() * rand();
            mp[{a, b, c, d}] = tmp;
            update(a, b, tmp);
            update(c + 1, d + 1, tmp);
            update(c + 1, b, -tmp);
            update(a, d + 1, -tmp);
        } else if(t == 2) {
            ll tmp = mp[{a, b, c, d}];
            mp[{a, b, c, d}] = 0;
            update(a, b, -tmp);
            update(c + 1, d + 1, -tmp);
            update(c + 1, b, tmp);
            update(a, d + 1, tmp);
        } else {
            ll t1 = query(a, b);
            ll t2 = query(c, d);
            if(t1 != t2) cout << "No
";
            else cout << "Yes
";
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/ftae/p/7733772.html