P5270 无论怎样神树大人都会删库跑路
题目地址:P5270 无论怎样神树大人都会删库跑路
第一眼看上去是模拟,似乎是 \(O(n)\) 的
水题
信心满满的写完:
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 6;
int n, T, Q, m, c[N], r[N], mx, cnt, d[N], ans, s[N], now;
vector<int> e[N];
queue<int> q;
int main() {
cin >> n >> T >> Q;
for (int i = 1; i <= T; i++) {
int x;
scanf("%d", &x);
mx = max(mx, x);
++c[x];
}
for (int i = 1; i <= n; i++) {
int len;
scanf("%d", &len);
while (len--) {
int x;
scanf("%d", &x);
mx = max(mx, x);
e[i].push_back(x);
}
}
cin >> m;
for (int i = 1; i <= m; i++) scanf("%d", &r[i]);
for (int x = 0; x <= mx; x++) if (c[x] == d[x]) ++cnt;
for (int i = 1; i <= m && i <= Q; i++) {
for (unsigned int j = 0; j < e[r[i]].size(); j++) {
int x = e[r[i]][j];
q.push(x);
if (d[x] == c[x]) --cnt;
++d[x];
if (d[x] == c[x]) ++cnt;
}
while ((int)q.size() > T) {
int x = q.front();
q.pop();
if (d[x] == c[x]) --cnt;
--d[x];
if (d[x] == c[x]) ++cnt;
}
if (cnt == mx + 1) ++ans;
}
if (Q <= m) {
cout << ans << endl;
return 0;
}
Q -= m;
for (int i = 1; i <= m; i++) {
for (unsigned int j = 0; j < e[r[i]].size(); j++) {
int x = e[r[i]][j];
q.push(x);
if (d[x] == c[x]) --cnt;
++d[x];
if (d[x] == c[x]) ++cnt;
}
while ((int)q.size() > T) {
int x = q.front();
q.pop();
if (d[x] == c[x]) --cnt;
--d[x];
if (d[x] == c[x]) ++cnt;
}
if (cnt == mx + 1) ++now;
s[i] = now;
}
cout << ans + now * (Q / m) + s[Q%m] << endl;
return 0;
}
Wait!
Q:为什么在模拟完第一遍后要再模拟一遍呢?
A:第一遍初始时没有数,而后面会有剩下的数留到下一轮,因此第一遍对 \(ans\) 的贡献要特判QAQ
一遍AC
然而......
模拟是 \(O(n)\) 的?
抱歉,假了,50分滚粗
康康这组数据:
1 1e5 1e9
1 1 ... 1
1e5 1 1 ... 1
1e5
1 1 ... 1
你会发现
被卡成 \(O(n^2)\) 了!
Q:怎么办?
A:骂毒瘤出题人
我们发现瓶颈在这:
for (unsigned int j = 0; j < e[r[i]].size(); j++) {
int x = e[r[i]][j];
q.push(x);
if (d[x] == c[x]) --cnt;
++d[x];
if (d[x] == c[x]) ++cnt;
}
while ((int)q.size() > T) {
int x = q.front();
q.pop();
if (d[x] == c[x]) --cnt;
--d[x];
if (d[x] == c[x]) ++cnt;
}
这个插入删除是 \(O(n)\) 的!
Q:我们能不能把它搞成 \(O(1)\) 的?
A:可以
考虑 Hash 思想
先看代码:
#include <bits/stdc++.h>
#define ull unsigned long long
#define pii pair<int, int>
using namespace std;
const int N = 1e5 + 6;
int n, T, Q, S[N], R[N], m, mx, len, ans, s[N], kkk;
vector<int> e[N];
struct H {
ull h[6];
H() {
memset(h, 0, sizeof(h));
}
} Hash[N], numS, now;
vector<H> num[N];
deque<pii> q;
inline ull RA() {
return (ull)rand() * rand() * rand() * rand() * rand() * rand();
}
inline void add(H &a, H &b) {
for (int i = 0; i < 6; i++) a.h[i] += b.h[i];
}
inline void del(H &a, H &b) {
for (int i = 0; i < 6; i++) a.h[i] -= b.h[i];
}
inline bool equ(H a, H b) {
for (int i = 0; i < 6; i++)
if (a.h[i] != b.h[i]) return 0;
return 1;
}
int main() {
srand((unsigned)time(0));
cin >> n >> T >> Q;
for (int i = 1; i <= T; i++) {
scanf("%d", &S[i]);
mx = max(mx, S[i]);
}
for (int i = 1; i <= n; i++) {
int len;
scanf("%d", &len);
while (len--) {
int x;
scanf("%d", &x);
mx = max(mx, x);
e[i].push_back(x);
}
}
cin >> m;
for (int i = 1; i <= m; i++) scanf("%d", &R[i]);
for (int i = 0; i <= mx; i++)
for (int j = 0; j < 6; j++)
Hash[i].h[j] = RA();
for (int i = 1; i <= T; i++) add(numS, Hash[S[i]]);
for (int i = 1; i <= n; i++) {
int len = e[i].size();
num[i].resize(len);
for (int j = len - 1; ~j; j--)
add(num[i][j], Hash[e[i][j]]);
for (int j = len - 2; ~j; j--)
add(num[i][j], num[i][j+1]);
}
for (int i = 1; i <= m && i <= Q; i++) {
add(now, num[R[i]][0]);
len += e[R[i]].size();
q.push_back({R[i], 0});
while (len > T) {
pii x = q.front();
q.pop_front();
del(now, num[x.first][x.second]);
len -= e[x.first].size() - x.second;
if (len < T) {
int k = num[x.first].size() - (T - len);
q.push_front({x.first, k});
add(now, num[x.first][k]);
len = T;
}
}
if (equ(now, numS)) ++ans;
}
if (Q <= m) {
cout << ans << endl;
return 0;
}
Q -= m;
for (int i = 1; i <= m && i <= Q; i++) {
add(now, num[R[i]][0]);
len += e[R[i]].size();
q.push_back({R[i], 0});
while (len > T) {
pii x = q.front();
q.pop_front();
del(now, num[x.first][x.second]);
len -= e[x.first].size() - x.second;
if (len < T) {
int k = num[x.first].size() - (T - len);
q.push_front({x.first, k});
add(now, num[x.first][k]);
len = T;
}
}
if (equ(now, numS)) ++kkk;
s[i] = kkk;
}
cout << ans + kkk * (Q / m) + s[Q%m] << endl;
return 0;
}
(小声)不好意思kkk,窝真的是没有变量名可用才用您的QWQ
我们给每个数若干维随机 Hash 值
for (int i = 0; i <= mx; i++)
for (int j = 0; j < 6; j++)
Hash[i].h[j] = RA();
一串数的 Hash 值定义为每个数的每一维 Hash 分别相加(unsigned long long自然溢出)
如果两个串任意排列后可以相同,这两个串对应的每一维都应该相同
那么插入和删除就都可以做到 \(O(1)\) 了
你卡我随机化鸭
你卡我 Hash 鸭
你卡我常数大鸭
P5270 无论怎样神树大人都会删库跑路的更多相关文章
- Mysql binlog备份数据及恢复数据,学会这个,我在也不怕删库跑路啦~
导读 我一直都主张,技多不压身(没有学不会的技术,只有不学习的人),多学一项技能,未来就少求人一次.网上经常听到xxx删库跑路,万一真的遇到了,相信通过今天的学习,也能将数据再恢复回来~~~ 当然啦, ...
- Oracle删库跑路
--10g R2 startup mount exclusive restrict; alter system enable restricted session; drop database; -- ...
- SQL 从入门到 DBA 删库跑路
SQL 从入门到 DBA 删库跑路 一.基础 人员信息表: ID 姓名 性别 出生 婚否 学历 工资 工会 35009449 孙xx 男 1978-2-17 未婚 中专 3000 TRUE 35000 ...
- 数据误操作,删库跑路?教你使用ApexSQLLog工具从 SQLServer日志恢复数据!
前几天同事不小心误操作,将SQLServer库的一张表的一个状态字段给刷成了一个统一状态,由于是update执行所以原来的相关状态无法确定.发生这种事情的时候我的小伙伴背后 一凉,估计心里里面想这怕是 ...
- 教你如何6秒钟往MySQL插入100万条数据!然后删库跑路!
教你如何6秒钟往MySQL插入100万条数据!然后删库跑路! 由于我用的mysql 8版本,所以增加了Timezone,然后就可以了 前提是要自己建好库和表. 数据库test, 表user, 三个字段 ...
- 【巨杉数据库SequoiaDB】巨杉Tech | “删库跑路”又出现,如何防范数据安全风险?
最近,又双叕有企业被“删库”了.来自微盟官网的消息,微盟的业务系统数据库(包括主备)遭遇其公司运维人员的删除,系统将停止运营超48小时. 频发的类似事件也让大家对于数据安全的关注不断提高.数据是一个科 ...
- The Data Way Vol.3|做到最后只能删库跑路?DBA 能做的还有很多
关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...
- 因为它,我差点删库跑路:js防抖与节流
前言 前端踩雷:短时间内重复提交导致数据重复. 对于前端大佬来说,防抖和节流的技术应用都是基本操作.对于"兼职"前端开发的来说,这些都是需要躺平的坑. 我们今天就来盘一盘js防抖与 ...
- 大数据开发从入门小白到删库跑路(一)- 获取Hadoop
Hadoop是一个可以通过相对简单编程模型实现跨多台计算机集群分布式处理大型数据集的框架.它不是依赖于高额成本的硬件可靠性来提供高可用性,Hadoop的设计能从单个服务器扩展到数千台机器,每个机器提供 ...
随机推荐
- jq实现百度图片移入移出内容提示框上下左右移动的效果
闲来无聊,看到百度图片hover的时候提示框的效果,遂想试一试自己能否实现. 百度图片hover的效果: 需求: 1. 当鼠标从图片上部移入的时候,提示框从上部移到正常位置.从上部移出的时候,提示框从 ...
- css3: 基本知识记录
1.transition过渡: 元素从一种样式到另一种样式添加效果: div { transition: width 2s, height 2s, transform 2s; -moz-transit ...
- 从LIst集合中安全的删除元素
package cn.rocker.list; import java.util.ArrayList; import java.util.Iterator; import java.util.List ...
- SpringBoot实战一:发送邮件
目录 邮件协议 引入邮件包 创建邮件类和测试类,写yml文件 文本邮件,HTML邮件,附件邮件,图片邮件 模板邮件 异常处理 来进行一个SpringBoot项目的实战,发送一下邮件,这里我们先了解一下 ...
- I/O模型之二:Linux IO模式及 select、poll、epoll详解
目录: <I/O模型之一:Unix的五种I/O模型> <I/O模型之二:Linux IO模式及 select.poll.epoll详解> <I/O模型之三:两种高性能 I ...
- webapi快速开发框架
一.webapi快速开发框架搭建之后台 从0开始搭建webapi基本框架.权限控制.异常管理.日志管理.缓存管理 源码:https://github.com/shengyu-kmust/webapi ...
- 使用 boot-repair 对 Windows + Ubuntu 双系统引导修复
问题描述: 由于在windows上进行更新/重装/修改了引导设置以后,windows会“自私”地重写引导,导致Ubuntu系统引导消失而无法选择Ubuntu启动.
- HDU 1011(星河战队 树形DP)
题意是说在一个洞穴中有许多房间,每个房间中有一些虫子和大脑,这些房间之间用隧道相连形成一棵树,士兵们杀虫子的能力有限,也可以直接杀死虫子而不消耗士兵战斗力,但这样就无法得到房间中的大脑,士兵们不能走回 ...
- Golang入门教程(十)内建函数
比较常用的内建函数 参考: http://blog.csdn.net/liumiaocn/article/details/54804074
- 关于Ant脚本
在开发中,一个项目要经历单元测试l,集成测试,系统测试,测试过程中可能要不断修改代码,Ant脚本,通过一个xml文件,封装一系列繁琐又常用的操作,通过Ant指令执行xml脚本来批处理创建删除任务,编译 ...