Codeforces 707D Persistent Bookcase 暴力(bitset)

来源:互联网 发布:恒大淘宝队 编辑:程序博客网 时间:2024/05/22 15:46
题意:书房有n个架子,每个架子有m层.q次操作.
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);elseupdate(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;}}


阅读全文
0 0
原创粉丝点击