博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【10.6校内测试】【小模拟】【hash+线段树维护覆盖序列】
阅读量:5323 次
发布时间:2019-06-14

本文共 6937 字,大约阅读时间需要 23 分钟。

一开始看到题就果断跳到T2了!!没想到T2才是个大坑,浪费了两个小时QAQ!!

就是一道小模拟,它怎么说就怎么走就好了!

为什么要用这么多感叹号!!因为统计答案要边走边统计!!如果每个数据都扫一遍2000*2000就炸了!!!

我爆哭QAQ再也不用stl的max叻!!(然而一定会被打脸)我的100分QAQAQAQ

#include
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
#define base 233using 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;}

 

转载于:https://www.cnblogs.com/wans-caesar-02111007/p/9747446.html

你可能感兴趣的文章
AFNetworking 2.0上传图片
查看>>
Web的几种上传方式总结
查看>>
保存新浪网首页到本地(使用urllib)
查看>>
html5.1版本
查看>>
Java网络编程基础【转】
查看>>
phpstudy apache无法启动
查看>>
判断对象是否存在 (if exists (select * from sysobjec...
查看>>
SVN检出后文件没有图标显示
查看>>
MPICH2在两台Ubuntu上安装
查看>>
jmete 取配置文件的行数(二)
查看>>
smortform 创建
查看>>
ng-class中的if else判断
查看>>
伪静态与重定向--RewriteBase
查看>>
“”.length()与“”.split(",").length
查看>>
如何让搜索引擎搜到自己的博客文章
查看>>
同步对象、信号量
查看>>
table标签
查看>>
hash
查看>>
Java内部类
查看>>
The Castle
查看>>