题解:P6532 [COCI 2015/2016 #1] TOPOVI

P6532 [COCI 2015/2016 #1] TOPOVI

分析

如果一个点不可以被攻击,那么列异或和异或行异或和为 0。

即如果对于一行来看,如果这一行所有元素都异或上了 x,那么不可以被攻击到的点的个数就是异或和为 x 的列数

那么如果加入修改,那么我们可以用 map 维护某一异或和对应的列数或行数,然后每次改变时更新。

那么就很好实现了。

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

unordered_map<int, ll> rxor, cxor, rcnt, ccnt;
map<pair<int, int>, int> mp;

int n, k, p;
ll ans = 0; // 可以被攻击到的点

void update(int x, int y, int w) {
    int R, C;
    R = rxor[x], C = cxor[y];
    ans -= n - rcnt[C] + n - ccnt[R];
    if (R ^ C) ans++;
    rcnt[R]--;
    ccnt[C]--;
    rxor[x] ^= w;
    cxor[y] ^= w;
    R = rxor[x], C = cxor[y];
    rcnt[rxor[x]]++;
    ccnt[cxor[y]]++;
    ans += n - rcnt[C] + n - ccnt[R];
    if (R ^ C) ans--;
    mp[{x, y}] ^= w;
}

int main() {
    cin >> n >> k >> p;
    rcnt[0] = ccnt[0] = n;
    for (int i = 1;i <= k;i++) {
        int x, y, w;
        cin >> x >> y >> w;
        update(x, y, w);
    }
    for (int i = 1;i <= p;i++) {
        int r1, r2, c1, c2;
        cin >> r1 >> c1 >> r2 >> c2;
        int w = mp[{r1, c1}];
        update(r1, c1, w);
        update(r2, c2, w);
        cout << ans << "\n";
    }
    return 0;
}
posted @ 2025-09-16 19:43  yanbinmu  阅读(3)  评论(0)    收藏  举报