题目地址:P5270 无论怎样神树大人都会删库跑路

第一眼看上去是模拟,似乎是 \(O(n)\) 的

水题

信心满满的写完:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int N = 1e5 + 6;
  4. int n, T, Q, m, c[N], r[N], mx, cnt, d[N], ans, s[N], now;
  5. vector<int> e[N];
  6. queue<int> q;
  7. int main() {
  8. cin >> n >> T >> Q;
  9. for (int i = 1; i <= T; i++) {
  10. int x;
  11. scanf("%d", &x);
  12. mx = max(mx, x);
  13. ++c[x];
  14. }
  15. for (int i = 1; i <= n; i++) {
  16. int len;
  17. scanf("%d", &len);
  18. while (len--) {
  19. int x;
  20. scanf("%d", &x);
  21. mx = max(mx, x);
  22. e[i].push_back(x);
  23. }
  24. }
  25. cin >> m;
  26. for (int i = 1; i <= m; i++) scanf("%d", &r[i]);
  27. for (int x = 0; x <= mx; x++) if (c[x] == d[x]) ++cnt;
  28. for (int i = 1; i <= m && i <= Q; i++) {
  29. for (unsigned int j = 0; j < e[r[i]].size(); j++) {
  30. int x = e[r[i]][j];
  31. q.push(x);
  32. if (d[x] == c[x]) --cnt;
  33. ++d[x];
  34. if (d[x] == c[x]) ++cnt;
  35. }
  36. while ((int)q.size() > T) {
  37. int x = q.front();
  38. q.pop();
  39. if (d[x] == c[x]) --cnt;
  40. --d[x];
  41. if (d[x] == c[x]) ++cnt;
  42. }
  43. if (cnt == mx + 1) ++ans;
  44. }
  45. if (Q <= m) {
  46. cout << ans << endl;
  47. return 0;
  48. }
  49. Q -= m;
  50. for (int i = 1; i <= m; i++) {
  51. for (unsigned int j = 0; j < e[r[i]].size(); j++) {
  52. int x = e[r[i]][j];
  53. q.push(x);
  54. if (d[x] == c[x]) --cnt;
  55. ++d[x];
  56. if (d[x] == c[x]) ++cnt;
  57. }
  58. while ((int)q.size() > T) {
  59. int x = q.front();
  60. q.pop();
  61. if (d[x] == c[x]) --cnt;
  62. --d[x];
  63. if (d[x] == c[x]) ++cnt;
  64. }
  65. if (cnt == mx + 1) ++now;
  66. s[i] = now;
  67. }
  68. cout << ans + now * (Q / m) + s[Q%m] << endl;
  69. return 0;
  70. }

Wait!

Q:为什么在模拟完第一遍后要再模拟一遍呢?

A:第一遍初始时没有数,而后面会有剩下的数留到下一轮,因此第一遍对 \(ans\) 的贡献要特判QAQ

一遍AC

然而......

模拟是 \(O(n)\) 的?

抱歉,假了,50分滚粗

康康这组数据:

  1. 1 1e5 1e9
  2. 1 1 ... 1
  3. 1e5 1 1 ... 1
  4. 1e5
  5. 1 1 ... 1

你会发现

被卡成 \(O(n^2)\) 了!

Q:怎么办?

A:骂毒瘤出题人

我们发现瓶颈在这:

  1. for (unsigned int j = 0; j < e[r[i]].size(); j++) {
  2. int x = e[r[i]][j];
  3. q.push(x);
  4. if (d[x] == c[x]) --cnt;
  5. ++d[x];
  6. if (d[x] == c[x]) ++cnt;
  7. }
  8. while ((int)q.size() > T) {
  9. int x = q.front();
  10. q.pop();
  11. if (d[x] == c[x]) --cnt;
  12. --d[x];
  13. if (d[x] == c[x]) ++cnt;
  14. }

这个插入删除是 \(O(n)\) 的!

Q:我们能不能把它搞成 \(O(1)\) 的?

A:可以

考虑 Hash 思想

先看代码:

  1. #include <bits/stdc++.h>
  2. #define ull unsigned long long
  3. #define pii pair<int, int>
  4. using namespace std;
  5. const int N = 1e5 + 6;
  6. int n, T, Q, S[N], R[N], m, mx, len, ans, s[N], kkk;
  7. vector<int> e[N];
  8. struct H {
  9. ull h[6];
  10. H() {
  11. memset(h, 0, sizeof(h));
  12. }
  13. } Hash[N], numS, now;
  14. vector<H> num[N];
  15. deque<pii> q;
  16. inline ull RA() {
  17. return (ull)rand() * rand() * rand() * rand() * rand() * rand();
  18. }
  19. inline void add(H &a, H &b) {
  20. for (int i = 0; i < 6; i++) a.h[i] += b.h[i];
  21. }
  22. inline void del(H &a, H &b) {
  23. for (int i = 0; i < 6; i++) a.h[i] -= b.h[i];
  24. }
  25. inline bool equ(H a, H b) {
  26. for (int i = 0; i < 6; i++)
  27. if (a.h[i] != b.h[i]) return 0;
  28. return 1;
  29. }
  30. int main() {
  31. srand((unsigned)time(0));
  32. cin >> n >> T >> Q;
  33. for (int i = 1; i <= T; i++) {
  34. scanf("%d", &S[i]);
  35. mx = max(mx, S[i]);
  36. }
  37. for (int i = 1; i <= n; i++) {
  38. int len;
  39. scanf("%d", &len);
  40. while (len--) {
  41. int x;
  42. scanf("%d", &x);
  43. mx = max(mx, x);
  44. e[i].push_back(x);
  45. }
  46. }
  47. cin >> m;
  48. for (int i = 1; i <= m; i++) scanf("%d", &R[i]);
  49. for (int i = 0; i <= mx; i++)
  50. for (int j = 0; j < 6; j++)
  51. Hash[i].h[j] = RA();
  52. for (int i = 1; i <= T; i++) add(numS, Hash[S[i]]);
  53. for (int i = 1; i <= n; i++) {
  54. int len = e[i].size();
  55. num[i].resize(len);
  56. for (int j = len - 1; ~j; j--)
  57. add(num[i][j], Hash[e[i][j]]);
  58. for (int j = len - 2; ~j; j--)
  59. add(num[i][j], num[i][j+1]);
  60. }
  61. for (int i = 1; i <= m && i <= Q; i++) {
  62. add(now, num[R[i]][0]);
  63. len += e[R[i]].size();
  64. q.push_back({R[i], 0});
  65. while (len > T) {
  66. pii x = q.front();
  67. q.pop_front();
  68. del(now, num[x.first][x.second]);
  69. len -= e[x.first].size() - x.second;
  70. if (len < T) {
  71. int k = num[x.first].size() - (T - len);
  72. q.push_front({x.first, k});
  73. add(now, num[x.first][k]);
  74. len = T;
  75. }
  76. }
  77. if (equ(now, numS)) ++ans;
  78. }
  79. if (Q <= m) {
  80. cout << ans << endl;
  81. return 0;
  82. }
  83. Q -= m;
  84. for (int i = 1; i <= m && i <= Q; i++) {
  85. add(now, num[R[i]][0]);
  86. len += e[R[i]].size();
  87. q.push_back({R[i], 0});
  88. while (len > T) {
  89. pii x = q.front();
  90. q.pop_front();
  91. del(now, num[x.first][x.second]);
  92. len -= e[x.first].size() - x.second;
  93. if (len < T) {
  94. int k = num[x.first].size() - (T - len);
  95. q.push_front({x.first, k});
  96. add(now, num[x.first][k]);
  97. len = T;
  98. }
  99. }
  100. if (equ(now, numS)) ++kkk;
  101. s[i] = kkk;
  102. }
  103. cout << ans + kkk * (Q / m) + s[Q%m] << endl;
  104. return 0;
  105. }

(小声)不好意思kkk,窝真的是没有变量名可用才用您的QWQ

我们给每个数若干维随机 Hash

  1. for (int i = 0; i <= mx; i++)
  2. for (int j = 0; j < 6; j++)
  3. Hash[i].h[j] = RA();

一串数的 Hash 值定义为每个数的每一维 Hash 分别相加(unsigned long long自然溢出)

如果两个串任意排列后可以相同,这两个串对应的每一维都应该相同

那么插入和删除就都可以做到 \(O(1)\) 了

你卡我随机化鸭

你卡我 Hash 鸭

你卡我常数大鸭

P5270 无论怎样神树大人都会删库跑路的更多相关文章

  1. Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~

    导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...

  2. Oracle删库跑路

    --10g R2 startup mount exclusive restrict; alter system enable restricted session; drop database; -- ...

  3. SQL 从入门到 DBA 删库跑路

    SQL 从入门到 DBA 删库跑路 一.基础 人员信息表: ID 姓名 性别 出生 婚否 学历 工资 工会 35009449 孙xx 男 1978-2-17 未婚 中专 3000 TRUE 35000 ...

  4. 数据误操作,删库跑路?教你使用ApexSQLLog工具从 SQLServer日志恢复数据!

    前几天同事不小心误操作,将SQLServer库的一张表的一个状态字段给刷成了一个统一状态,由于是update执行所以原来的相关状态无法确定.发生这种事情的时候我的小伙伴背后 一凉,估计心里里面想这怕是 ...

  5. 教你如何6秒钟往MySQL插入100万条数据!然后删库跑路!

    教你如何6秒钟往MySQL插入100万条数据!然后删库跑路! 由于我用的mysql 8版本,所以增加了Timezone,然后就可以了 前提是要自己建好库和表. 数据库test, 表user, 三个字段 ...

  6. 【巨杉数据库SequoiaDB】巨杉Tech | “删库跑路”又出现,如何防范数据安全风险?

    最近,又双叕有企业被“删库”了.来自微盟官网的消息,微盟的业务系统数据库(包括主备)遭遇其公司运维人员的删除,系统将停止运营超48小时. 频发的类似事件也让大家对于数据安全的关注不断提高.数据是一个科 ...

  7. The Data Way Vol.3|做到最后只能删库跑路?DBA 能做的还有很多

    关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...

  8. 因为它,我差点删库跑路:js防抖与节流

    前言 前端踩雷:短时间内重复提交导致数据重复. 对于前端大佬来说,防抖和节流的技术应用都是基本操作.对于"兼职"前端开发的来说,这些都是需要躺平的坑. 我们今天就来盘一盘js防抖与 ...

  9. 大数据开发从入门小白到删库跑路(一)- 获取Hadoop

    Hadoop是一个可以通过相对简单编程模型实现跨多台计算机集群分布式处理大型数据集的框架.它不是依赖于高额成本的硬件可靠性来提供高可用性,Hadoop的设计能从单个服务器扩展到数千台机器,每个机器提供 ...

随机推荐

  1. 关键字(8):数据库记录的增删查改insert,delete,select,update

    insert:一般只要参数个数和类型没问题,不会插入异常 INSERT INTO t_pos_dynamic_map(autoid, lt_termno, lt_merchno) VALUES(SEQ ...

  2. Linux虚拟内存(swap)调优篇-“swappiness”,“vm.dirty_background_ratio”和“vm.dirty_ratio”

      Linux虚拟内存(swap)调优篇-“swappiness”,“vm.dirty_background_ratio”和“vm.dirty_ratio” 作者:尹正杰 版权声明:原创作品,谢绝转载 ...

  3. python 函数动态参数,名称空间,global,nonlocal

    ##################################总结######################################动态参数 *args:位置参数动态传参,接收到的是元 ...

  4. SpringBoot系列: Redis 共享Session

    Web项目Session管理是一个很重要的话题, 涉及到系统横向扩展, SpringBoot已经为共享Session很好的解决方案, 这篇文章关注使用Redis共享会话, 同时这也是最常用的方法. = ...

  5. vue 组件动态 循环

    组件可以是动态的,记录如下 <div v-for="item in arrComponent"> <component v-bind:is="item. ...

  6. IScroll在某些手机浏览器上不能滑动和卡顿解决办法

    1.不能滑动,增加一句 if (scroll != null) scroll.refresh();2.卡顿,增加 <script>window.PointerEvent = undefin ...

  7. 解决 Android Device Monitor 常见问题

    Ø  简介 什么是 Android Device Monitor,中文意思就是安卓设备监视器,用于管理安装设备(手机.模拟器)用的.下面列出 Android Device Monitor 常见的一些问 ...

  8. 24.join算法/锁_1

    一. JOIN算法1.1. JOIN 语法 mysql> select * from t4; +---+------+ | a | b | +---+------+ | | 11 | | | 5 ...

  9. IDAPython教程(三)

    在过去两个部分中,我们已经讨论了使用IDAPython让逆向工程更容易一些.这一部分我们来看一下条件断点. 当在IDA中调试时,分析者经常会遇到希望可以在一个特殊的地址中断下来的情况,但这只有在一些特 ...

  10. 【python小练】图片爬虫之BeautifulSoup4

    Python3用不了Scrapy! Python3用不了Scrapy! Python3用不了Scrapy! [重要的事情说三遍,据说大神们还在尝试把scrapy移植到python3,特么浪费我半个小时 ...