Codeforces Round #368 (Div. 2) D Persistent Bookcase(离线+DFS)

来源:互联网 发布:php运费模板源码 编辑:程序博客网 时间:2024/06/06 07:15

思路:离线把所有操作都存起来,并且对于前三个操作连i-1到i的边,第四个操作回到第K个结点那么连k到i的边,然后DFS记录变化就可以了,这个过程对于第一次接触可能不太好理解,可以结合代码看

注意:加书本的时候如果本来就有的话这个操作相当于无效,同理对于去掉一本书,DFS的时候回溯的时候记得把原来标记的状态变回原来的


#include<bits/stdc++.h>using namespace std;const int maxn =1005;const int maxq = 1e5+7;int a[maxn][maxn],ans[maxq],op[maxq];pair<int,int>op1[maxq];vector<int>e[maxq];int sum = 0;int n,m,q;void dfs(int x){if(op[x]!=4)      ans[x]=sum;elsesum=ans[x];int nn,mm;for(int i = 0;i<e[x].size();i++){int v = e[x][i];if(op[v]==1){int op1flag=0;            if(a[op1[v].first][op1[v].second]==0){ a[op1[v].first][op1[v].second]=1;    sum++;op1flag = 1;}nn = op1[v].first;mm = op1[v].second;dfs(v);        if(op1flag)                a[nn][mm]=0,sum--;}if(op[v]==2){int op2flag = 0;if(a[op1[v].first][op1[v].second]==1)   a[op1[v].first][op1[v].second]=0,sum--,op2flag=1;nn=op1[v].first,mm=op1[v].second;dfs(v);    if(op2flag)        a[nn][mm]=1,sum++;}if(op[v]==3){nn = op1[v].first;for(int j = 1;j<=m;j++){if(a[nn][j]){a[nn][j]=0;sum--;}else{a[nn][j]=1;sum++;}}dfs(v);        for(int j = 1;j<=m;j++)    {    if(a[nn][j])    {    a[nn][j]=0;    sum++;    }    else    {    a[nn][j]=1;    sum--;    }    } }if(op[v]==4){ans[v]=ans[op1[v].first];dfs(v);}}}int main(){   scanf("%d%d%d",&n,&m,&q);   for(int i = 1;i<=q;i++)   {   scanf("%d",&op[i]);   if(op[i]==1)   {   int nn,mm;   scanf("%d%d",&nn,&mm);   op1[i]=make_pair(nn,mm);           e[i-1].push_back(i);   }   if(op[i]==2)   {   int nn,mm;   scanf("%d%d",&nn,&mm);   op1[i]=make_pair(nn,mm);   e[i-1].push_back(i);   }   if(op[i]==3)   {   int nn;   scanf("%d",&nn);   op1[i]=make_pair(nn,-1);   e[i-1].push_back(i);   }   if(op[i]==4)   {   int k;   scanf("%d",&k);   e[k].push_back(i);   op1[i] = make_pair(k,-1);   }   }   dfs(0);   for(int i = 1;i<=q;i++)   printf("%d\n",ans[i]);}



0 0