Problem

Description

人们总是难免会碰到大佬。他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语。你作为一个 OIer,面对这样的事情非常不开心,于是发表了对大佬不敬的言论。 大佬便对你开始了报复,你也不示弱,扬言要打倒大佬。现在给你讲解一下什么是大佬,大佬除了是神犇以外,还有着强大的自信心,自信程度可以被量化为一个正整数 \(C\),想要打倒一个大佬的唯一方法是摧毁 Ta 的自信心,也就是让大佬的自信值等于 \(0\)(恰好等于 \(0\),不能小于 \(0\))。由于你被大佬盯上了,所以你需要准备好 \(n\) 天来和大佬较量,因为这 \(n\) 天大佬只会嘲讽你动摇你的自信,到了第 \(n+1\) 天,如果大佬发现你还不服,就会直接虐到你服,这样你就丧失斗争的能力了。

你的自信程度同样也可以被量化,我们用 \(\mathrm{mc}\) 来表示你的自信值上限。在第 \(i \ (i\ge 1)\) 天,大佬会对你发动一次嘲讽,使你的自信值减小 \(a_i\),如果这个时刻你的自信值小于 \(0\) 了,那么你就丧失斗争能力,也就失败了(特别注意你的自信值为 \(0\) 的时候还可以继续和大佬斗争)。 在这一天,大佬对你发动嘲讽之后,如果你的自信值仍大于等于 \(0\),你能且仅能选择如下的行为之一

  1. 还一句嘴,大佬会有点惊讶,导致大佬的自信值 \(C\) 减小 \(1\)。

  2. 做一天的水题,使得自己的当前自信值增加 \(w_i\),并将新自信值和自信值上限 \(\mathrm{mc}\) 比较,若新自信值大于 \(\mathrm{mc}\),则新自信值更新为 \(\mathrm{mc}\)。例如,\(\mathrm{mc} = 50\),当前自信值为 \(40\),若 \(w_i = 5\),则新自信值为 \(45\),若 \(w_i = 11\),则新自信值为 \(50\)。

  3. 让自己的等级值 \(L\) 加 \(1\)。

  4. 让自己的讽刺能力 \(F\) 乘以自己当前等级 \(L\),使讽刺能力 \(F\) 更新为 \(F\cdot L\)。

  5. 怼大佬,让大佬的自信值 \(C\) 减小 \(F\)。并在怼完大佬之后,你自己的等级 \(L\) 自动降为 \(0\),讽刺能力 \(F\) 降为 \(1\)。由于怼大佬比较掉人品,所以这个操作只能做不超过两次

特别注意的是,在任何时候,你不能让大佬的自信值为负,因为自信值为负,对大佬来说意味着屈辱,而大佬但凡遇到屈辱就会进化为更厉害的大佬直接虐飞你。在第 \(1\) 天,在你被攻击之前,你的自信是满的(初始自信值等于自信值上限 \(\mathrm{mc}\)),你的讽刺能力 \(F\) 是 \(1\),等级是 \(0\)。

现在由于你得罪了大佬,你需要准备和大佬正面杠,你知道世界上一共有 \(m\) 个大佬,他们的嘲讽时间都是 \(n\) 天,而且第 \(i\) 天的嘲讽值都是 \(a_i\)。不管和哪个大佬较量,你在第 \(i\) 天做水题的自信回涨都是 \(w_i\)。这 \(m\) 个大佬中只会有一个来和你较量(\(n\) 天里都是这个大佬和你较量),但是作为你,你需要知道对于任意一个大佬,你是否能摧毁他的自信,也就是让他的自信值恰好等于 \(0\)。和某一个大佬较量时,其他大佬不会插手。

Input Format

第一行三个正整数 \(n,m,\mathrm{mc}\)。分别表示有 \(n\) 天和 \(m\) 个大佬,你的自信上限为 \(\mathrm{mc}\)。

接下来一行是用空格隔开的 \(n\) 个数,其中第 \(i(1\le i\le n)\) 个表示 \(a_i\)。

接下来一行是用空格隔开的 \(n\) 个数,其中第 \(i(1\le i\le n)\) 个表示 \(w_i\)。

接下来 \(m\) 行,每行一个正整数,其中第 \(k(1\le k\le m)\) 行的正整数 \(C_k\) 表示第 \(k\) 个大佬的初始自信值。

Output Format

共 \(m\) 行,如果能战胜第 \(k\) 个大佬(让他的自信值恰好等于 0),那么第 \(k\) 行输出 \(1\),否则输出 \(0\)。

Sample

Input

  1. 30 20 30
  2. 15 5 24 14 13 4 14 21 3 16 7 4 7 8 13 19 16 5 6 13 21 12 7 9 4 15 20 4 13 12
  3. 22 21 15 16 17 1 21 19 11 8 3 28 7 10 19 3 27 17 28 3 26 4 22 28 15 5 26 9 5 26
  4. 30
  5. 10
  6. 18
  7. 29
  8. 18
  9. 29
  10. 3
  11. 12
  12. 28
  13. 11
  14. 28
  15. 6
  16. 1
  17. 6
  18. 27
  19. 27
  20. 18
  21. 11
  22. 26
  23. 1

Output

  1. 0
  2. 1
  3. 1
  4. 0
  5. 1
  6. 0
  7. 1
  8. 1
  9. 0
  10. 0
  11. 0
  12. 1
  13. 1
  14. 1
  15. 1
  16. 1
  17. 1
  18. 0
  19. 0
  20. 1

Range

对于 \(20\%\) 的数据,\(1\le n\le 10\);

另有 \(20\%\) 数据,\(1\le C_i,n,\mathrm{mc}\le 30\);

对于 \(100\%\) 的数据,\(1\le n, \mathrm{mc}\le 100, 1\le m\le 20; 1\le a_i, w_i\le\mathrm{mc}, 1\le C_i\le 10^8\)。

Algorithm

\(DP\),广搜

Mentality

我感觉我做了一道搜索题 \(......\) 蓝瘦。而且题面也太过真实了。

我们第一个瞬间就该发现,每个大佬只有血量不同,那么我们为了打败大佬,肯定要用尽量多的时间来降低他的自信,则由于其他量都相等,我们完全可以先求出最多能用多少天来与大佬战♂斗对抗。

这个很简单,来一发 \(DP\) 就好,设 \(f[i][j]\) 为到了第 \(i\) 天剩余 \(j\) 点自信时,最多能花多少天嘲讽大佬。然后取 \(n^2\) 数组内的最大值 \(D\) 作为最大天数。

然后我们要统计如何分配怼大佬的那两次。

首先,如果大佬的自信值小于等于 \(D\) ,我们直接不停还嘴就行。

那么我们讨论一下怼大佬的情况。

先计算出我们的嘲讽能力为 \(F\) 时所需花费的最小天数 \(D\) ,求法后面再讲,它太过暴力了 \(emm...\) 。

我们考虑枚举两次怼大佬时的嘲讽能力 \(F1,F2\) ,显然在相同 \(F\) 值的情况下花在准备上的时间要越少越好,我们设两者的时间为 \(D1,D2\)。

那么我们这两次怼大佬必定要满足两个条件:不能把大佬怼死了;剩下的时间通过还嘴可以刚好打败大佬。

转化成不等式如下:

\[F1+F2\le C ,F1+F2+(D-D1-D2)\ge C
\]

那我们只需要枚举一个 \(F1\) ,在这种情况下,\(F1,D1\) 都已经固定了,我们可以找到一个满足第一个不等式的,具有最优性的 \(F2\) ,也即 \(F2-D2\) 在满足第一个不等式的条件下最小,那么这时我们计算 \(F1+F2+(D-D1-D2)\) 是否大于等于 \(C\) ,如果大于则此次询问答案为 \(YES\) ,如果枚举遍所有的 \(F1\) 都无法满足第二个不等式那答案就为 \(NO\) 。

所以我们可以把所有计算出来的状态按 \(F\) 排序,然后从大到小枚举 \(F1\) ,而 \(F2\) 的寻找范围也是单调递增的,那么我们扫 \(F2\) 的指针沿用上次的即可。

那么重点来了,怎么计算状态呢?答案是 -- 广搜 \(......\)

我们只需要带着三个数值所代表的状态 \(dfs\) 即可,分别是 \(step\) -- 使用 \(step\) 天,\(L\) -- 当前等级,\(F\) -- 当前嘲讽能力。然后直接广搜肯定是不行的,我们来观察一下:由于在相同的 \(F\) 下,所花天数越小越好。而由于我们使用的是广搜,所以当我们搜索到一个新状态 \(step,L,F\) 时,相对于当前的 \(L,F\) ,\(step\) 就肯定是最优天数了。所以我们只需要使用哈希表判重,如果后面再搜到相同的 \(L,F\) ,那就不加入搜索队列了。

暴力否?

如若不懂详见代码。

为了卡常长得蛮奇怪。

Code

  1. #include <algorithm>
  2. #include <cstdio>
  3. #include <iostream>
  4. #include <queue>
  5. using namespace std;
  6. #define f(i) STA[i].first
  7. #define d(i) STA[i].second
  8. const int mod = 9e5 + 1;
  9. int n, m, limit, maxx, cnt, C, a[101], w[101], c[21];
  10. int f[101][101], D;
  11. inline void read(int &x) {
  12. x = 0;
  13. char ch = getchar();
  14. while (!isdigit(ch)) ch = getchar();
  15. while (isdigit(ch)) {
  16. x = x * 10 + ch - '0';
  17. ch = getchar();
  18. }
  19. }
  20. pair<int, int> STA[1000001];
  21. struct node {
  22. int L, F, t;
  23. };
  24. struct Check {
  25. int x[mod], y[mod], nx[mod], head[mod], cnt;
  26. int get_key(int X, int Y) { return (998244ll * X + Y) % mod; }
  27. inline void add(int X, int Y) {
  28. int now = get_key(X, Y);
  29. cnt++;
  30. nx[cnt] = head[now], x[cnt] = X, y[cnt] = Y;
  31. head[now] = cnt;
  32. }
  33. inline bool query(int X, int Y) {
  34. int now = get_key(X, Y);
  35. for (register int i = head[now]; i; i = nx[i])
  36. if (X == x[i] && Y == y[i]) return true;
  37. return false;
  38. }
  39. } Map, M;
  40. inline void Max(int &a, int b) { a = a < b ? b : a; }
  41. queue<node> q;
  42. inline void bfs() {
  43. q.push((node){0, 1, 1});
  44. while (!q.empty()) {
  45. node now = q.front();
  46. q.pop();
  47. if (now.t == D) continue;
  48. q.push((node){now.L + 1, now.F, now.t + 1});
  49. if (now.L > 1 && 1ll * now.L * now.F <= maxx &&
  50. !Map.query(now.L * now.F, now.L)) //手写 Map 判重
  51. {
  52. int A = now.L * now.F, B = now.t + 1;
  53. q.push((node){now.L, A, B});
  54. if (!M.query(A, 9181283))
  55. STA[++cnt] = make_pair(A, B),
  56. M.add(A, 9181283); //相同 F 下所花天数越少越好
  57. Map.add(A, now.L);
  58. }
  59. }
  60. }
  61. int main() {
  62. read(n), read(m), read(limit);
  63. for (register int i = 1; i <= n; i++) read(a[i]);
  64. for (register int i = 1; i <= n; i++) read(w[i]);
  65. for (register int i = 1; i <= m; i++)
  66. read(c[i]), Max(maxx, c[i]); //先处理出搜索的上限 -- F
  67. //值至少不能大于自信值最强的大佬的自信吧
  68. for (register int i = 1; i <= n; i++)
  69. for (register int j = a[i]; j <= limit; j++)
  70. Max(f[i][j - a[i]], f[i - 1][j] + 1),
  71. Max(f[i][min(limit, j - a[i] + w[i])],
  72. f[i - 1][j]); //先 DP 出最大天数
  73. for (register int i = 1; i <= n; i++)
  74. for (register int j = 1; j <= limit; j++) Max(D, f[i][j]); //取 max
  75. bfs(); //开始广搜
  76. sort(STA + 1, STA + cnt + 1);
  77. for (register int i = 1; i <= m; i++) {
  78. if (c[i] <= D) {
  79. printf("1\n");
  80. continue;
  81. }
  82. int mmax = -1e9, Ans = 0;
  83. for (register int l = 1, r = cnt; r; r--) {
  84. while (f(l) + f(r) <= c[i] && l < cnt)
  85. Max(mmax, f(l) - d(l)), l++; //移动
  86. if (f(r) + D - d(r) + mmax >= c[i]) Ans = 1; //是否满足第二个不等式
  87. if (f(r) <= c[i] && f(r) + D - d(r) >= c[i]) Ans = 1;
  88. }
  89. printf("%d\n", Ans);
  90. }
  91. }

【HNOI 2017】大佬的更多相关文章

  1. [HNOI 2017]大佬

    Description 题库链接 题意简述来自Gypsophila. 你现在要怼 \(m\) 个大佬,第 \(i\) 个大佬的自信值是 \(C_i\) .每次怼大佬之前,你的自信值是 \(mc\),等 ...

  2. [HNOI 2017]单旋

    Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的 ...

  3. [HNOI 2017]抛硬币

    Description 题库链接 两人抛硬币一人 \(a\) 次,一人 \(b\) 次.记正面朝上多的为胜.问抛出 \(a\) 次的人胜出的方案数. \(1\le a,b\le 10^{15},b\l ...

  4. [HNOI 2017]影魔

    Description 题库链接 给你一段长度为 \(n\) 的序列 \(K\) . \(m\) 组询问,每次给定左右端点 \(l,r\) .求出满足区间内下述贡献和. 如果一个区间的两个端点是这一个 ...

  5. [HNOI 2017]礼物

    Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在 ...

  6. 【HNOI 2017】影魔

    Problem Description 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还 ...

  7. HNOI 2017

    题目链接 我还是按bzoj AC数量排序做的 4827 这个其实如果推一下(求每个值)式子会发现是个卷积,然后FFT就好了 4826 记不太清了,可以求出每个点左右第一个比他的的点的位置,将点对看成平 ...

  8. 【HNOI 2017】礼物

    Problem Description 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手环,一个留给自己,一个送给她.每个手环上各有 \(n\) 个装饰物,并且每个装饰物 ...

  9. AH/HNOI 2017 礼物

    题目链接 描述 两个序列 \(x, y\),可以将一个序列每个值同时加非负整数 \(c\),其中一个序列可以循环移位,要求最小化: \[\sum_{i = 1}^{n}(x_i - y_i) ^ 2 ...

随机推荐

  1. docker命令汇总

    docker命令汇总 序号 类别 简述 命令 功能 说明 1 整体管理 安装 yum install docker-engine centos上安装docker Ubuntu上安装dockerapt- ...

  2. oracle储存过程学习笔记

    转载至: https://www.2cto.com/database/201610/559389.htm 1.什么是oracle存储过程 存储过程和函数也是一种PL/SQL块,是存入数据库的PL/SQ ...

  3. Python3学习之路~7.1 静态方法、类方法、属性方法

    静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量 ...

  4. MATLAB程序控制语句

    Matlab中的程序控制语句包括条件控制(Conditional Control).循环(Loop Control).异常处理(Error Control)和程序返回(Program Terminat ...

  5. python发送邮件心得体会

    利用本地smtp server发送 windows下尝试装了两个smtp server大概配置了下,发现没法生效,也没时间仔细研究了.装上foxmail发现以前可以本地发送的选项已经无法找到. 不带附 ...

  6. 关于sql server profiler 监控工具的使用

    勾选以下属性: 记录这个数据库访问磁盘的次数:

  7. 67.web--手机端兼容性问题

    H5页面窗口自动调整到设备宽度,并禁止用户缩放页面 <meta name="viewport" content="width=device-width,initia ...

  8. windows10误删Administrator用户的家目录之后

    今天在玩Windows10的用户管理的时候,把Administrator用户给开启了,然后还用这个用户登录了系统. 结果就是,第一次登录的时候,闪过一条条初始化配置欢迎信息,Windows系统为Adm ...

  9. jpa 使用笔记

    1,嵌套类查询 List<Person> findByAddress_ZipCode(ZipCode zipCode); ZipCode是Address属性的内部属性. 2,jpa in ...

  10. XiangBai——【CVPR2018】Multi-Oriented Scene Text Detection via Corner Localization and Region Segmentation

    XiangBai——[CVPR2018]Multi-Oriented Scene Text Detection via Corner Localization and Region Segmentat ...