题目链接:D Persistent Bookcase

题意:有一个n*m的书架,开始是空的,现在有k种操作:

1 x y 这个位置如果没书,放书。

2 x y 这个位置如果有书,拿走。

3 x 反转这一行,即有书的位置拿走,没书的位置放上书。

4 x 返回到第x步操作之后的书架。

现在给出q个操作,询问每次操作之后书架上书的数量。

思路:

开始没有思路。后来被告知dfs。

【词不达意。参考:http://blog.csdn.net/zyjhtutu/article/details/52279494】

对于第i次操作的后的书架,要么是由第i-1次操作后的书架得到的,要么是返回到第x步。而,每一步得到的书架书的数量只有一种可能。

将操作看成边,当前的状态看作节点,建树。建树的规则是,如果进行的操作树1或者2或者3,那么就将操作后状态连接在当前状态后面

,如果操作是4,就将操作后的状态连接在要还原的状态后面。然后进行dfs,离线求解。dfs的巧妙之处在于,由于数据量比较大,不可

能将每次操作后的状态都记下来。其实,仔细想想,根本不需要记录所有的状态,只需要记录当前状态,然后dfs,回溯的时候将更改的

状态在改回来。这样,一边dfs就解决问题。时间复杂度为q*m。

附代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <vector>
#define maxn 100100
using namespace std; vector<int> nxt[maxn];
int ans[maxn];
int op[maxn], r[maxn], c[maxn];
bool vis[1010][1010]; //标记当前状态是否已经有书
int n, m; void init() {
ans[0] = 0;
for (int i=1; i<=maxn; ++i) {
nxt[i].clear();
}
memset(vis, 0, sizeof(vis));
} void dfs(int x) {
for (int i=0; i<nxt[x].size(); ++i) {
int nxts = nxt[x][i]; // 从x出发能到达的所有状态
//cout << nxts << " " << op[nxts] << "...\n";
if (op[nxts] == 1) {
if (vis[r[nxts]][c[nxts]]) { // 已经有书
ans[nxts] = ans[x];
dfs(nxts);
}
else {
vis[r[nxts]][c[nxts]] = 1;
ans[nxts] = ans[x] + 1;
dfs(nxts);
vis[r[nxts]][c[nxts]] = 0;
}
}
else if (op[nxts] == 2) {
if (vis[r[nxts]][c[nxts]] == 0) { // 没书
ans[nxts] = ans[x];
dfs(nxts);
}
else {
vis[r[nxts]][c[nxts]] = 0;
ans[nxts] = ans[x] - 1;
dfs(nxts);
vis[r[nxts]][c[nxts]] = 1;
}
}
else if (op[nxts] == 3) {
int cnt = 0;
for (int j=1; j<=m; ++j) {
if (vis[r[nxts]][j] == 0) {
cnt++;
vis[r[nxts]][j] = 1;
}
else {
cnt--;
vis[r[nxts]][j] = 0;
}
}
ans[nxts] = ans[x] + cnt;
dfs(nxts);
for (int j=1; j<=m; ++j) {
if (vis[r[nxts]][j] == 0) {
vis[r[nxts]][j] = 1;
}
else vis[r[nxts]][j] = 0;
}
}
else if (op[nxts] == 4) {
ans[nxts] = ans[x];
dfs(nxts);
}
}
} int main() {
// freopen("in.cpp", "r", stdin);
int q;
while(~scanf("%d%d%d", &n, &m, &q)) {
init();
for (int i=1; i<=q; ++i) {
scanf("%d", &op[i]);
if (op[i] == 1 || op[i] == 2) {
scanf("%d%d", &r[i], &c[i]);
nxt[i-1].push_back(i);
}
else if (op[i] == 3) {
scanf("%d", &r[i]);
nxt[i-1].push_back(i);
}
else if (op[i] == 4) {
scanf("%d", &r[i]);
nxt[r[i]].push_back(i);
}
} dfs(0);
for (int i=1; i<=q; ++i) {
printf("%d\n", ans[i]);
}
}
return 0;
}

确实很巧妙。

CodeForces #368 div2 D Persistent Bookcase DFS的更多相关文章

  1. codeforces 707D D. Persistent Bookcase(dfs)

    题目链接: D. Persistent Bookcase time limit per test 2 seconds memory limit per test 512 megabytes input ...

  2. 【Codeforces-707D】Persistent Bookcase DFS + 线段树

    D. Persistent Bookcase Recently in school Alina has learned what are the persistent data structures: ...

  3. Codeforces Round #368 (Div. 2)D. Persistent Bookcase DFS

    题目链接:http://codeforces.com/contest/707/my 看了这位大神的详细分析,一下子明白了.链接:http://blog.csdn.net/queuelovestack/ ...

  4. CodeForces #369 div2 D Directed Roads DFS

    题目链接:D Directed Roads 题意:给出n个点和n条边,n条边一定都是从1~n点出发的有向边.这个图被认为是有环的,现在问你有多少个边的set,满足对这个set里的所有边恰好反转一次(方 ...

  5. Codeforces Round #368 (Div. 2) D. Persistent Bookcase

    Persistent Bookcase Problem Description: Recently in school Alina has learned what are the persisten ...

  6. Codeforces Round #368 (Div. 2) D. Persistent Bookcase 离线 暴力

    D. Persistent Bookcase 题目连接: http://www.codeforces.com/contest/707/problem/D Description Recently in ...

  7. Persistent Bookcase CodeForces - 707D (dfs 离线处理有根树模型的问题&&Bitset)

    Persistent Bookcase CodeForces - 707D time limit per test 2 seconds memory limit per test 512 megaby ...

  8. D. Persistent Bookcase(Codeforces Round #368 (Div. 2))

    D. Persistent Bookcase time limit per test 2 seconds memory limit per test 512 megabytes input stand ...

  9. CF #368 div2

    题目链接:http://codeforces.com/contest/707/problem/A A. Brain's Photos time limit per test 2 seconds mem ...

随机推荐

  1. Codeforces617 E . XOR and Favorite Number(莫队算法)

    XOR and Favorite Number time limit per test: 4 seconds memory limit per test: 256 megabytes input: s ...

  2. noi 6047 分蛋糕

    题目链接:http://noi.openjudge.cn/ch0405/6047/ 和Uva1629很类似,不过,可能用记忆化难写一点,状态初始化懒得搞了.就用循环好了. 状态描叙也可以修改,那个题目 ...

  3. laravel框架总结(十一) -- 集合

      创建集合: collect 辅助函数会利用传入的数组生成一个新的 Illuminate\Support\Collection 实例. $collection = collect([1, 2, 3] ...

  4. 【转】C#使用ESC指令控制POS打印机打印小票

    .前言 C#打印小票可以与普通打印机一样,调用PrintDocument实现.也可以发送标注你的ESC指令实现.由于 调用PrintDocument类时,无法操作使用串口或TCP/IP接口连接的pos ...

  5. sublime text 配置 builder [build system]

    有时候需要用运行一段 PHP 代码,比如测试某个函数返回值等等,如果启动 Http Server,再打开浏览器,那黄花菜都凉了.我们可以在 Sublime Text 3 中创建 PHP 的 build ...

  6. angular的双向数据绑定

    方向1:模型数据(model) 绑定 到视图(view) 实现方法1:{{model变量名}} $scope.num=10 <p>{{num}}</p> 实现方法2: 常用指令 ...

  7. JDBC相关的类介绍

    JDBC 背景:1996年,Sun公司推出了Java数据库连接(Java Database Connectivity JDBC)工具包的第一个版本.该工具包使得程序员可以使用结构化语言SQL连接到一个 ...

  8. NiosII常用函数整理

    NiosII常用函数整理 IO操作函数函数原型:IORD(BASE, REGNUM) 输入参数:BASE为寄存器的基地址,REGNUM为寄存器的偏移量函数说明:从基地址为BASE的设备中读取寄存器中偏 ...

  9. 微信小程序-视图条件渲染

    条件渲染 wx:if 在框架中,我们用 wx:if="{{condition}}" 来判断是否需要渲染该代码块: <view wx:if="{{condition} ...

  10. 框架整合----------Hibernate、spring整合

    说到整合框架,其实也就是环境的搭建了,首先我们要导包,这里连接数据库我们用到了spring容器,我们用连接池来进行数据库的连接,我们需要导入c3p0和jdbc的jar包,其余的就是spring和Hib ...