【10.6校内测试】【小模拟】【hash+线段树维护覆盖序列】
一开始看到题就果断跳到T2了!!没想到T2才是个大坑,浪费了两个小时QAQ!!
就是一道小模拟,它怎么说就怎么走就好了!
为什么要用这么多感叹号!!因为统计答案要边走边统计!!如果每个数据都扫一遍2000*2000就炸了!!!
我爆哭QAQ再也不用stl的max叻!!(然而一定会被打脸)我的100分QAQAQAQ
#include<bits/stdc++.h> using namespace std; int k, n; int vis[2005][2005]; char s[105]; int main() { freopen("block.in", "r", stdin); freopen("block.out", "w", stdout); int T; scanf("%d", &T); while(T --) { scanf("%d", &k); scanf("%s", s); int now = 0; memset(vis, 0, sizeof(vis)); vis[1000][1000] ++; int lx = 1000, ly = 1000, rx = 1001, ry = 1001; int ans = 0; for(int i = 0; i < strlen(s); i ++) { char opt = s[i]; if(opt == 'N') { if(now) { if(rx == lx + 1) { vis[lx][ly+k] ++; if(vis[lx][ly+k] > ans) ans = vis[lx][ly+k]; ly = ry, ry ++; now = 0; } else { for(int p = lx; p < rx; p ++) { vis[p][ry] ++; if(vis[p][ry] > ans) ans = vis[p][ry]; } ly ++, ry ++; } } else { for(int p = ly + 1; p <= ly + k; p ++) { vis[lx][p] ++; if(vis[lx][p] > ans) ans = vis[lx][p]; } ly ++; ry += k; now = 1; } } else if(opt == 'S') { if(now) { if(rx == lx + 1) { vis[lx][ly-1] ++; if(vis[lx][ly-1] > ans) ans = vis[lx][ly-1]; ly --; ry = ly + 1; now = 0; } else { for(int p = lx; p < rx; p ++) { vis[p][ly-1] ++; if(vis[p][ly-1] > ans) ans = vis[p][ly-1]; } ly --; ry --; } } else { for(int p = ly - 1; p >= ly - k; p --) { vis[lx][p] ++; if(ans < vis[lx][p]) ans = vis[lx][p]; } ry = ly; ly = ly - k; now = 1; } } else if(opt == 'W') { if(now) { if(rx == lx + 1) { for(int p = ly; p < ry; p ++) { vis[lx-1][p] ++; if(vis[lx-1][p] > ans) ans = vis[lx-1][p]; } lx --; rx --; } else { vis[lx-1][ly] ++; if(vis[lx-1][ly] > ans) ans = vis[lx-1][ly]; lx --; rx -= k; now = 0; } } else { for(int p = lx - k; p < lx; p ++) { vis[p][ly] ++; if(vis[p][ly] > ans) ans = vis[p][ly]; } lx -= k; rx --; now = 1; } } else { if(now) { if(rx == lx + 1) { for(int p = ly; p < ry; p ++) { vis[lx+1][p] ++; if(vis[lx+1][p] > ans) ans = vis[lx+1][p]; } lx ++; rx ++; } else { vis[lx+k][ly] ++; if(vis[lx+k][ly] > ans) ans = vis[lx+k][ly]; lx += k; rx ++; now = 0; } } else { for(int p = lx + 1; p < rx + k; p ++) { vis[p][ly] ++; if(vis[p][ly] > ans) ans = vis[p][ly]; } lx ++; rx += k; now = 1; } } } if(rx == lx + 1) { int sum = ry - ly; for(int i = 1; i < sum; i ++) printf("%d ", lx - 1000); printf("%d", lx - 1000); printf("\n"); for(int i = ly; i < ry-1; i ++) printf("%d ", i - 1000); printf("%d", ry - 1001); printf("\n"); } else { int sum = rx - lx; for(int i = lx; i < rx-1; i ++) printf("%d ", i - 1000); printf("%d", rx - 1001); printf("\n"); for(int i = 1; i < sum; i ++) printf("%d ", ly - 1000); printf("%d", ly - 1000); printf("\n"); } printf("%d\n", ans); } return 0; }
这道题暴力分拿的太爽了,15分钟敲出来70分成了救命稻草QAQAQ
区间修改考虑线段树。
因为目标的覆盖序列只有一个,就是1~k。其他的序列都不合法,怎么才能在最后快速判断是否合法呢?
想到$hash$,每次覆盖相当于在$hash$序列中加一个数,在线段树上转化成了$*A+B$($A$就是$base$,$B$就是新增的数),于是就可以维护了。
最后查询$Dfs$将每个叶子节点的$hash$值存下来即可。
#include<bits/stdc++.h> #define base 233 using namespace std; int n, k, t; unsigned int tag1[800005], tag2[800005]; unsigned int TR[800005], has[200005]; void build(int nd, int l, int r) { tag1[nd] = 1; tag2[nd] = 0; if(l == r) return ; int mid = (l + r) >> 1; build(nd << 1, l, mid); build(nd << 1 | 1, mid + 1, r); } void push_down(int nd, int l, int r) { if(tag1[nd] != 1 || tag2[nd] != 0) { TR[nd<<1] = TR[nd<<1] * tag1[nd] + tag2[nd]; TR[nd<<1|1] = TR[nd<<1|1] * tag1[nd] + tag2[nd]; tag1[nd<<1] = tag1[nd] * tag1[nd<<1]; tag1[nd<<1|1] = tag1[nd] * tag1[nd<<1|1]; tag2[nd<<1] = tag1[nd] * tag2[nd<<1] + tag2[nd]; tag2[nd<<1|1] = tag1[nd] * tag2[nd<<1|1] + tag2[nd]; tag1[nd] = 1; tag2[nd] = 0; } } void modify(int nd, int l, int r, int L, int R, int d) { if(l >= L && r <= R) { TR[nd] = TR[nd] * base + d; tag2[nd] = tag2[nd] * base + d; tag1[nd] = tag1[nd] * base; return ; } push_down(nd, l, r); int mid = (l + r) >> 1; if(L <= mid) modify(nd << 1, l, mid, L, R, d); if(R > mid) modify(nd << 1 | 1, mid + 1, r, L, R, d); } void query(int nd, int l, int r) { if(l == r) { has[l] = TR[nd]; return ; } push_down(nd, l, r); int mid = (l + r) >> 1; query(nd << 1, l, mid); query(nd << 1 | 1, mid + 1, r); } int main() { freopen("deco.in", "r", stdin); freopen("deco.out", "w", stdout); scanf("%d%d%d", &n, &k, &t); build(1, 1, n); for(int i = 1; i <= t; i ++) { int a, b, c; scanf("%d%d%d", &a, &b, &c); modify(1, 1, n, a, b, c); } query(1, 1, n); int h = 0; for(int i = 1; i <= k; i ++) h = h * base + i; int ans = 0; for(int i = 1; i <= n; i ++) if(has[i] == h) ans ++; printf("%d", ans); return 0; }