[CF707D] Persistent Bookcase
Description
维护一个二维零一矩阵(\(n,m \le 1000\)),支持四种操作(不超过 \(10^5\) 次),将 (i,j) 置一,将 (i,j) 置零,将第 i 行零一反转,回到第 K 次操作前的状态。每次操作后输出全局一共有多少个一。
Solution
对操作过程建树,然后 DFS
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1005;
bitset<N> a[N];
tuple<int, int, int> op[N * N];
vector<int> g[N * N];
int n, m, q, ans[N * N];
int cur = 0;
void dfs(int p)
{
auto [x, y, z] = op[p];
int old = a[min(1000ll, y)][z];
if (x == 1)
{
if (a[y][z] == 0)
++cur;
a[y][z] = 1;
}
if (x == 2)
{
if (a[y][z] == 1)
--cur;
a[y][z] = 0;
}
if (x == 3)
{
cur -= a[y].count();
a[y].flip();
if (a[y][N - 1])
cur -= N - m;
else
cur += N - m;
cur += a[y].count();
}
ans[p] = cur;
for (int q : g[p])
dfs(q);
if (x == 1)
{
a[y][z] = old;
if (a[y][z] == 0)
--cur;
}
if (x == 2)
{
a[y][z] = old;
if (a[y][z] == 1)
++cur;
}
if (x == 3)
{
cur -= a[y].count();
a[y].flip();
if (a[y][N - 1])
cur -= N - m;
else
cur += N - m;
cur += a[y].count();
}
}
signed main()
{
ios::sync_with_stdio(false);
cin >> n >> m >> q;
for (int i = 1; i <= q; i++)
{
int t1, t2, t3 = 0;
cin >> t1 >> t2;
if (t1 < 3)
cin >> t3;
op[i] = {t1, t2, t3};
if (t1 == 4)
g[t2].push_back(i);
else
g[i - 1].push_back(i);
}
dfs(0);
for (int i = 1; i <= q; i++)
{
cout << ans[i] << endl;
}
}