题意:书房有n个架子,每个架子有m层.q次操作.
op1:第i个架子的第j层放一本书, op2:拿走第i个架子的第j层上的书.
op3:反转第i个架子:将第i个架子中有书的拿走,没书的放书.op4:把书房恢复到第k次操作后的状态.
n,m<1e3,q<=1e5.问每次操作后,当前书的数量.
在线:(i,j)二维可以转换成一维i*m+j 前三个操作相等于线段树的单点置0/1和区间反转.
op1:第i个架子的第j层放一本书, op2:拿走第i个架子的第j层上的书.
op3:反转第i个架子:将第i个架子中有书的拿走,没书的放书.op4:把书房恢复到第k次操作后的状态.
n,m<1e3,q<=1e5.问每次操作后,当前书的数量.
离线:因为每次暴力更新加上bitset优化区间翻转后复杂度为O(mq/32).则把每个op看成图中的结点.
第i次若进行op4则将i连到x结点之后,否则将i连接到i-1结点后.dfs暴力更新.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e3+20;
const int M=2e5+20;
const ll inf=2e16;
int n,m,q,ans[M],tot;
int op[M],x[M],y[M];
bitset<N> b[N],all;
vector<int> e[M];
void dfs(int u)
{
bool flag=false;
if(op[u]==1&&b[x[u]][y[u]]==0)
flag=true,b[x[u]][y[u]]=1,tot++;
if(op[u]==2&&b[x[u]][y[u]])
flag=true,b[x[u]][y[u]]=0,tot--;
if(op[u]==3)
{
flag=true;
tot-=b[x[u]].count();
b[x[u]]^=all;
tot+=b[x[u]].count();
}
ans[u]=tot;
for(int i=0;i<e[u].size();i++)
dfs(e[u][i]);
if(flag)//bt
{
if(op[u]==1)
tot--,b[x[u]][y[u]]=0;
if(op[u]==2)
tot++,b[x[u]][y[u]]=1;
if(op[u]==3)
tot-=b[x[u]].count(),b[x[u]]^=all,tot+=b[x[u]].count();
}
}
int main()
{
while(cin>>n>>m>>q)
{
for(int i=1;i<=m;i++)
all.set(i);
tot=0;
memset(ans,-1,sizeof(ans));
for(int i=1;i<=q;i++)
{
scanf("%d%d",&op[i],&x[i]);
if(op[i]==4)
e[x[i]].push_back(i);
else if(op[i]<3)
scanf("%d",&y[i]);
if(op[i]<4)
e[i-1].push_back(i);
}
dfs(0);
for(int i=1;i<=q;i++)
printf("%d\n",ans[i]);
}
return 0;
}
在线:(i,j)二维可以转换成一维i*m+j 前三个操作相等于线段树的单点置0/1和区间反转.
可持久化一下保存前i次询问时线段树的状态.
某dalao代码:
#include <iostream>
#include <bitset>
using namespace std;
bitset<1005> bs[100005*20];
int sum[100005*20], rt[10000005], tail;
int ls[100005*20], rs[100005*20], M;
void build(int l, int r, int& root){
root = ++tail;
if(l == r) return;
int m = (l + r)/2;
build(l, m, ls[root]);
build(m+1, r, rs[root]);
}
void update(int l, int r, int pre, int& now, int op, int x, int y = 0){
now = ++tail;
ls[now] = ls[pre];
rs[now] = rs[pre];
if(l == r){
bs[now] = bs[pre];
if(op == 1){
bs[now].set(y-1, 1);
}else if(op == 2){
bs[now].set(y-1, 0);
}else{
for(int i = 0; i < M; i ++){
bs[now].flip(i);
}
}
sum[now] = bs[now].count();
return;
}
int m = (l + r)/2;
if(x <= m) update(l, m, ls[pre], ls[now], op, x, y);
else update(m+1, r, rs[pre], rs[now], op, x, y);
sum[now] = sum[ls[now]] + sum[rs[now]];
}
int main(){
int n, q;
cin >> n >> M >> q;
build(1, n, rt[0]);
for(int i = 1; i <= q; i ++){
int op;
cin >> op;
if(op == 4){
int x;
cin >> x;
rt[i] = rt[x];
}else if(op == 3){
int x;
cin >> x;
update(1, n, rt[i-1], rt[i], op, x);
}else{
int x, y;
cin >> x >> y;
update(1, n, rt[i-1], rt[i], op, x, y);
}
cout << sum[rt[i]] << endl;
}
}