Codeforces #386 Ddfs+bitset

    xiaoxiao2022-06-29  33

    题目链接

    相关知识


    bitset使用 :http://blog.csdn.net/qll125596718/article/details/6901935


    解析


    本题的棘手之处在于题目中的第4个操作。在不能改变时间的情况下,状态只能随着时间的推进而转移(一维)。现在可以改变时间,那么状态的转移目的地就不唯一了,也就是说状态的转移会出现分叉。那么状态的转移的图示就从一个数轴变成了一棵树(二维)。如果我们能够构造出这棵树,就能在用 DFS 状态转移的同时计算出每个状态下的书本的数量了。

    令询问 i 的时刻为 i ,并对每个时刻设立一个树节点。那么当操作编号为 1,2 或 3 的时候,我们就让 i−1 时刻到 i 时刻连一条单向边,当操作编号为 4 的时候相当于将时刻改变为 k ,那么我们就让 k 时刻到 i 时刻连一条单向边。这样就能构造出我们要的“状态转移树”了。

    当然,要在状态转移的过程中计算出书本的数量也并非十分容易的事。关键就在于怎么表示状态。设时刻 i 书本的总数为 res ,我们定义一个 n×m 的矩阵,矩阵的每个元素代表书架的这个位置是否有书。在转移状态的过程中维护这个矩阵就能应付前两个操作(维护 res ),第三个操作要遍历一整行(修改,求和),能否避免这种遍历呢?bitset很好的节省了时间。


    代码

    #include<cstdio> #include<cstring> #include <iostream> #include <queue> #include <vector> #include <bitset> using namespace std; const int maxn = 1000+10; const int inf = 0x3f3f3f3f; typedef pair<int, int> P; int n, m, q; struct node { int com, i, j; }op[100000+10]; vector<int>g[100000+10]; int ans[100000+10]; int vis[100000+10]; bitset<maxn>bit[maxn]; int X[maxn]; int res; void dfs(int u) { ans[u] = res; for (int i=0; i<g[u].size(); i++) { int v = g[u][i]; int pre = res; bitset<1010>b; int tmp = X[op[v].i]; b = bit[op[v].i]; if (op[v].com == 1) { int x = op[v].i, y = op[v].j; if (!bit[x].test(y)) { res++; bit[x].set(y); } } else if (op[v].com == 2) { int x = op[v].i, y=op[v].j; if (bit[x].test(y)) { res--; bit[x].reset(y); } } else if (op[v].com == 3) { int x=op[v].i; if (X[x] % 2 == 0) { int num = b.count(); X[x]++; int ren = m-num; res += (ren-num); bit[x].flip(); } else { int num = bit[x].count()-1010+m; X[x]++; res += (m-2*num); bit[x].flip(); } } dfs(v); res = pre; bit[op[v].i] = b; X[op[v].i] = tmp; } } int main() { res = 0; scanf("%d%d%d", &n, &m, &q); for (int i=0; i<=q; i++) g[i].clear(); for (int i=1; i<=q; i++) { int com; scanf("%d", &com); if (com <= 2) { op[i].com = com; scanf("%d%d", &op[i].i, &op[i].j); g[i-1].push_back(i); } else if (com == 3) { op[i].com = com; scanf("%d", &op[i].i); g[i-1].push_back(i); } else if (com == 4) { int k; scanf("%d", &k); g[k].push_back(i); } } dfs(0); for (int i=1; i<=q; i++) printf("%d\n", ans[i]); return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-1125283.html

    最新回复(0)