Codeforces Round #368 (Div. 2) D - Persistent Bookcase
2016-08-22 19:34
260 查看
题目大意是对一个n层,每层有m个位置的书架进行4种操作:
1)在位置(i,j)上放一本书,如果已经有书,则不在方书
2)拿走位置(i,j)上的一本书,如果没书,则不能拿走
3)将第i层的所有位置的状态翻转,如果某位子有书,则拿走,如果某位置没书,则放一本书
4)将书架的状态还原到之前的某个状态
比赛的时候这个题目并没有思路,最后看了别人思路。自己写了一下。觉得方法比较巧妙,所以写博客记之,以便以后回顾。题目要求每次操作的后输出当前书架上的书的数量。我们需要将操作看成边,当前的状态看作节点,建树。建树的规则是,如果进行的操作树1或者2或者3,那么就将操作后状态连接在当前状态后面,如果操作是4,就将操作后的状态连接在要还原的状态后面。然后进行dfs,离线求解。dfs的巧妙之处在于,由于数据量比较大,不可能将每次操作后的状态都记下来。其实,仔细想想,根本不需要记录所有的状态,只需要记录当前状态,然后dfs,回溯的时候将更改的状态在改回来。这样,一边dfs就解决问题。时间复杂度为q*m。下面贴上代码
1)在位置(i,j)上放一本书,如果已经有书,则不在方书
2)拿走位置(i,j)上的一本书,如果没书,则不能拿走
3)将第i层的所有位置的状态翻转,如果某位子有书,则拿走,如果某位置没书,则放一本书
4)将书架的状态还原到之前的某个状态
比赛的时候这个题目并没有思路,最后看了别人思路。自己写了一下。觉得方法比较巧妙,所以写博客记之,以便以后回顾。题目要求每次操作的后输出当前书架上的书的数量。我们需要将操作看成边,当前的状态看作节点,建树。建树的规则是,如果进行的操作树1或者2或者3,那么就将操作后状态连接在当前状态后面,如果操作是4,就将操作后的状态连接在要还原的状态后面。然后进行dfs,离线求解。dfs的巧妙之处在于,由于数据量比较大,不可能将每次操作后的状态都记下来。其实,仔细想想,根本不需要记录所有的状态,只需要记录当前状态,然后dfs,回溯的时候将更改的状态在改回来。这样,一边dfs就解决问题。时间复杂度为q*m。下面贴上代码
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> using namespace std; const int MAX = 100010; const int MAXN = 1010; struct Node{ int x,y,z; }p[MAX]; vector<int>G[MAX]; int mark[MAXN][MAXN]; int d[MAX],n,m,q; void init(){ d[0] = 0; memset(mark, 0, sizeof(mark)); for (int i = 0; i<MAX; i++) G[i].clear(); } void dfs(int u){ for (int i = 0; i<G[u].size(); i++){ int v = G[u][i]; int s = p[v].y, t = p[v].z; if (p[v].x == 1){ if (mark[s][t] == 1){ d[v] = d[u]; dfs(v); } else{ mark[s][t] = 1; d[v] = d[u] + 1; dfs(v); mark[s][t] = 0; } } if (p[v].x == 2){ if (mark[s][t] == 0){ d[v] = d[u]; dfs(v); } else{ mark[s][t] = 0; d[v] = d[u] - 1; dfs(v); mark[s][t] = 1; } } if (p[v].x == 3){ int cnt = 0; for (int j = 1; j<=m; j++){ if (mark[s][j] == 1){ cnt--; mark[s][j] = 0; } else{ cnt++; mark[s][j] = 1; } } d[v] = d[u] + cnt; dfs(v); for (int j = 1; j<=m; j++){ if (mark[s][j] == 0){ mark[s][j] = 1; } else{ mark[s][j] = 0; } } } if (p[v].x == 4){ d[v] = d[u]; dfs(v); } } } int main(){ while (scanf("%d%d%d",&n,&m, &q) != EOF){ init(); for (int i = 1; i<=q; i++){ scanf("%d", &p[i].x); if (p[i].x==1 || p[i].x == 2){ scanf("%d%d",&p[i].y, &p[i].z); G[i-1].push_back(i); } if (p[i].x == 3){ scanf("%d", &p[i].y); G[i-1].push_back(i); } if (p[i].x == 4){ scanf("%d", &p[i].y); G[p[i].y].push_back(i); } } dfs(0); for (int i = 1; i<=q; i++) printf("%d\n", d[i]); } return 0; }
相关文章推荐
- Codeforces Round #368 (Div. 2) [D] Persistent Bookcase
- Codeforces Round #368 (Div. 2)D. Persistent Bookcase DFS
- Codeforces Round #178 (Div. 2) B .Shaass and Bookshelf
- Codeforces Round #310 (Div. 1) B. Case of Fugitive set
- 贪心/思维题 Codeforces Round #310 (Div. 2) C. Case of Matryoshkas
- Codeforces Round #310 (Div. 1) B. Case of Fugitive
- Codeforces Round #196 (Div. 2) D. Book of Evil 树形dp
- codeforces # 317 div 2 B. Order Book(模拟)
- Lesson 37 Making a bookcase 做书架
- Codeforces Round #310 (Div. 2) A. Case of the Zeros and Ones 水题
- Codeforces Round #416 (Div. 2) B. Vladik and Complicated Book
- Codeforces Round #368 (Div. 2) D. Persistent Bookcase 离线 暴力
- Codeforces Round #368 (Div. 2) D. Persistent Bookcase(n层m个的书架的四种操作)
- Codeforces Round #310 (Div. 2) B. Case of Fake Numbers 水题
- Codeforces Round #310 (Div. 1) B. Case of Fugitive 贪心
- Codeforces Round #368 (Div. 2) D. Persistent Bookcase 离线 dfs+bitset
- HLG 1532 The Bookcase
- Codeforces Round #178 (Div. 2) B .Shaass and Bookshelf
- 【暑假】[深入动态规划]UVa 10618 The Bookcase
- Codeforces Round #416 (Div. 2) B. Vladik and Complicated Book