http://codeforces.com/contest/707/problem/D
维护一个n*m的矩阵
题意就是4个操作,操作1,给a[i][j]置1
操作2,置零
操作3,第i行取反
操作4,回到做了k步之后的状态
---------------------------离线的做法:-------------------------------------------------------------------------------------------------------------------
把询问离线,按顺序建树,按照dfs序跑一遍就得到答案了】
例如操作i和i+1都是 非4的操作
那么i+1的父亲就是i咯,
如果i是4操作,那么i的父亲就会是k
那么按照这个顺序来跑一遍答案,就OK了,记得跑完x的操作后回溯的时候要撤掉操作(还原)
操作12都是单点,操作3用个数组记一下就好了。。。。都是o1的。。。。。
。比赛时sb了 怼了个bitset。。。估计会T 复杂度 O(q*n/64)
(居然没T,嘿嘿)
-------------------------------------------------------------------------------------------------------------------
--------------------------------------在线的做法-------------------------------------------------------------------------------------------------------------------
对于每一行书柜,我们用一个主席树维护m列的值,相当于n棵咯。
然后我们再开一个主席树,维护的是n行书柜对应主席树的根节点。
每次修改的时候,我们先在第n+1棵主席树找到 第x行对应的根节点,然后再在该树X上修改值。
每次新建2*logn个节点
空间复杂度q*logn
时间复杂度q*logn
....也很优秀,,不过还是离线了比较好搞。。。
确实大概类似与 一个可持久化数组套一个可持久化数组?
离线AC代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <bitset>
#include <vector>
#include <iostream>
using namespace std;
const double pi=acos(-1.0);
double eps=0.000001;
typedef long long ll;
struct node
{
int kind,x,y;
};
vector<int >mp[100050];
int equ[100050];
node tt[100050];
int fa[100050];
bitset<1005> sb[1005];
int ans[100050];
int num=0;
int n,m,q;
void deal(int x,int& vaild)
{
int k=tt[x].kind;
int i=tt[x].x;
int j=tt[x].y;
if (k==1)
{
if (!sb[i][j]) sb[i][j]=1,num++,vaild=1;
else vaild=0;
}
if (k==2)
{
if ( sb[i][j]) sb[i][j]=0,num--,vaild=1;
else vaild=0;
}
if (k==3)
{
int cun=sb[i].count();
if (sb[i][1004]==1) cun-=(1005-m);
num=num-cun+(m-cun);
sb[i]=~sb[i];
}
if (k==4)
{
}
}
void redeal(int x,int& vaild)
{
int k=tt[x].kind;
int i=tt[x].x;
int j=tt[x].y;
if (k==1)
{
if (vaild) sb[i][j]=0,num--;
}
if (k==2)
{
if (vaild) sb[i][j]=1,num++;
}
if (k==3)
{
int cun=sb[i].count();
if (sb[i][1004]==1) cun-=(1005-m);
num=num-cun+(m-cun);
sb[i]=~sb[i];
}
if (k==4)
{
}
}
void dfs(int x)
{
int vaild;
if (x)
{
deal(x,vaild);
ans[x]=num;
}
for (int i=0; i<mp[x].size(); i++)
{
int v=mp[x][i];
dfs(v);
}
if (x);
redeal(x,vaild);
}
int main()
{
for (int i=1; i<=10000; i++) equ[i]=i,fa[i]=i;
fa[1]=0;
cin>>n>>m>>q;
num=0;
for (int i=1; i<=q; i++)
{
scanf("%d",&tt[i].kind);
if (tt[i].kind<=2)
scanf("%d%d",&tt[i].x,&tt[i].y);
else scanf("%d",&tt[i].x);
}
for (int i=2; i<=q; i++)
{
if (tt[i].kind!=4)
{
// fa[i]=equ[i-1];
mp[i-1].push_back(i);
}
else
{
// equ[i]=tt[i].x+1;
// fa[i]=fa[equ[i]];
mp[tt[i].x].push_back(i);
}
}
mp[0].push_back(1);
dfs(0);
for (int i=1; i<=q; i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
主席树代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std;
const int MAXNN=1e5 + 50;
const int MAXNnode=(2e5)*11 ;
#define w(i) T[(i)].w
#define ls(i) T[(i)].ls
#define rs(i) T[(i)].rs
int n;
struct node
{
int ls,rs,w;
node()
{
ls=rs=w=0;
}
} T[MAXNnode];
int root[MAXNN],sz,m;
struct any
{
int x,y,z;
any() {}
any(int a,int b,int c)
{
x=a,y=b,z=c;
}
};
any getid(int i,int l,int r,int x)//取出在i时间的第x行对应的主席树的根节点
{
if (l==r) return any(T[i].w,T[i].ls,T[i].rs);
int m=(l+r)>>1;
if (x<=m) return getid(ls(i),l,m,x);
else return getid(rs(i),m+1,r,x);
}
void changeId(int &i,int l,int r,int x,any res)//修改在i时间的第x行对应的主席树子节点
{
T[++sz]=T[i];
i=sz;
if (l==r)
{
T[i].w=res.x,T[i].ls=res.y,T[i].rs=res.z;
return ;
}
int m=(l+r)>>1;
if (x<=m) changeId(ls(i),l,m,x,res);
else changeId(rs(i),m+1,r,x,res);
}
int getval(int i,int l,int r,int x) //取得某行对应的第x列的值
{
if (r==l) return T[i].w;
int m=(r+l)>>1;
if (x<=m) return getval(ls(i),l,m,x);
else return getval(rs(i),m+1,r,x);
}
void changeVal(int &i,int l,int r,int x)//修改某行对应的第x列的值
{
T[++sz]=T[i];
i=sz;
if (r==l)
{
T[i].w^=1;
return ;
}
int m=(r+l)>>1;
if (x<=m) changeVal(ls(i),l,m,x);
else changeVal (rs(i),m+1,r,x);
}
int ans[100005];
int main()
{
//DO YOLO
root[0]=0;
sz=0;
int n;
int m,q;
cin>>n>>m>>q;
int kind,x,y;
for (int i=1; i<=q; i++)
{
root[i]=root[i-1];
ans[i]=ans[i-1];
scanf("%d",&kind);
if (kind==1)
{
scanf("%d%d",&x,&y);
any res=getid(root[i],1,n,x);
int val=getval(res.x,1,m,y);
if ((val^res.y)==0)
{
int id=res.x;
changeVal(id,1,m,y);
res.z++;
res.x=id;
changeId(root[i],1,n,x,res);
ans[i]++;
}
}
else if (kind==2)
{
scanf("%d%d",&x,&y);
any res=getid(root[i],1,n,x);
int val=getval(res.x,1,m,y);
if ((val^res.y)==1)
{
int id=res.x;
changeVal(id,1,m,y);
res.z--;
res.x=id;
changeId(root[i],1,n,x,res);
ans[i]--;
}
}
else if (kind==3)
{
scanf("%d",&x);
any res=getid(root[i],1,n,x);
int changeNum=m-res.z-res.z;
ans[i]+=changeNum;
res.y^=1;
res.z+=changeNum;
changeId(root[i],1,n,x,res);
}
else
{
scanf("%d",&x);
root[i]=root[x];
ans[i]=ans[x];
}
printf("%d\n",ans[i]);
}
return 0;
}