CF# 368 D2 D
很容易想到可以它操作序列弄成有向图,果断深搜。但我开始竟然用了一种特醇的方法,每个书架做一次深搜,复杂度O(nq),跑到57个test就不动了。看看代码吧
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> //#include <bitset> using namespace std; const int MAXOPT = 100005; struct OPT{ int opt, r, c; }op[MAXOPT]; struct bits{ char s[125]; void init(){ for(int i = 0; i < 125; i++) s[i] = 0; } bool find(int k){ int p = k / 8; int m = k % 8; if(s[p] & (1<<m)) return true; return false; } void set(int k){ int p = k / 8; int m = k % 8; s[p] |= (1<<m); } void reset(int k){ int p = k / 8; int m = k % 8; s[p] ^= (1<<m); } void flip(){ for(int i = 0; i < 125; i++){ s[i] ^= (-1); } } }; struct STATE{ bits st; void init(){ st.init(); counts = 0; } int counts; }; vector<int>nt[MAXOPT]; int ans[MAXOPT]; int n, m, q; void dfs(int pos, STATE iter, int sh){ int sz = nt[pos].size(); for(int k = 0; k < sz; k++){ ans[nt[pos][k]] += iter.counts; dfs(nt[pos][k], iter, sh); } while(op[pos + 1].opt != 4 && pos < q){ pos ++; if(op[pos].r == sh){ if(op[pos].opt == 1){ if(!iter.st.find(op[pos].c - 1)){ iter.counts++; iter.st.set(op[pos].c - 1); } } else if(op[pos].opt == 2){ if(iter.st.find(op[pos].c - 1)){ iter.counts --; iter.st.reset(op[pos].c - 1); } } else { iter.st.flip(); iter.counts = m - iter.counts; } } ans[pos] += iter.counts; int sz = nt[pos].size(); for(int k = 0; k < sz; k++){ ans[nt[pos][k]] += iter.counts; dfs(nt[pos][k], iter, sh); } } } int main(){ int opt, r, c; memset(ans, 0, sizeof(ans)); scanf("%d%d%d", &n, &m, &q); for(int i = 0; i <= q; i++) nt[i].clear(); for(int i = 1; i <= q; i++){ scanf("%d", &op[i].opt); if(op[i].opt == 1 || op[i].opt == 2){ scanf("%d%d", &op[i].r, &op[i].c); } else { scanf("%d", &op[i].r); } if(op[i].opt == 4){ nt[op[i].r].push_back(i); } } for(int i = 1; i <= n; i++){ STATE iter; iter.init(); ans[0] += iter.counts; dfs(0, iter, i); } for(int i = 1; i <= q; i++){ printf("%d\n", ans[i]); } return 0; }
后来想到,一次操作只动一个书架,深搜之后把原来的状态还原回去就可以啦,复杂度O(q)。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> //#include <bitset> using namespace std; const int MAXOPT = 100005; int state[1005][1005]; int n, m, q; struct operation{ int op, r, c; }op[MAXOPT]; int ans[MAXOPT]; vector<int> nt[MAXOPT]; void dfs(int u){ int sz = nt[u].size(); for(int i = 0; i < sz; i++){ int v = nt[u][i]; if(op[v].op == 1){ int pre = state[op[v].r][op[v].c]; if(!pre){ state[op[v].r][op[v].c] = 1; ans[v] = ans[u] + 1; } else ans[v] = ans[u]; dfs(v); state[op[v].r][op[v].c] = pre; } else if(op[v].op == 2){ int pre = state[op[v].r][op[v].c]; if(pre){ state[op[v].r][op[v].c] = 0; ans[v] = ans[u] - 1; } else ans[v] = ans[u]; dfs(v); state[op[v].r][op[v].c] = pre; } else if(op[v].op == 3){ int c = 0; for(int k = 1; k <=m; k++){ if(state[op[v].r][k]) c++; state[op[v].r][k] ^= 1; } ans[v] = ans[u] - c + m - c; dfs(v); for(int k = 1; k <=m; k++){ state[op[v].r][k] ^= 1; } } else{ ans[v] = ans[u]; dfs(v); } } } int main(){ scanf("%d%d%d", &n, &m, &q); memset(ans, 0, sizeof(ans)); memset(state, 0, sizeof(state)); for(int i = 1; i <= q; i++){ scanf("%d", &op[i].op); if(op[i].op == 1 || op[i].op == 2){ scanf("%d%d", &op[i].r, &op[i].c); } else{ scanf("%d", &op[i].r); } if(op[i].op == 4) nt[op[i].r].push_back(i); else nt[i - 1].push_back(i); } dfs(0); for(int i = 1; i <= q; i++) printf("%d\n", ans[i]); return 0; }