哎……做了几个小时最后还是没能想到怼大佬的合法性到底怎么搞。写暴力爆搜感觉复杂度爆炸就没敢写 bfs / dfs 一类,后来发现在种种的约束条件下(远小于所给的 \(n, m\))复杂度完全是可以承受的。不过就算想到了这一步谅我也想不出用单调栈来搞两次的组合吧。

  这题最开始就应该发现:扣血和回血完全是可以分开的两个操作。为什么这个点很容易发现呢:1.扣血的多少与时间是无关的。2.本题要求活着(血量 >= 0)而非最大化血量。所以第一步显然应当 dp 出在保证活着的前提下最多能够空出多少天来对付 ‘大佬’。

  然后来考虑,假设我们最多拥有 \(D\) 天来攻击,是否存在一种攻击方案使得'大佬'的血量正好为0。预处理出 \(g[k][d]\) 代表 \(d\) 次操作,是否可能对'大佬'产生 \(k\) 点伤害。(这里用Map来存储,并注意这里的方案只考虑怼一次)。然后我们假设存在一种合法的方案怼大佬两次使得大佬血量正好为0,第一次扣血 \(f1\) 点,耗费时间为 \(d1\) 天,第二次扣血 \(f2\) 点,耗费时间为 \(d2\) 天。他们之间该满足什么样的关系式呢? (设大佬血量为 \(M\))

\(M >= f1 + f2\)

\(M - f1 - f2 <= D - d1 - d2\)

  其中(1)式表示不能减为负数,(2)式表示没有减完的血量可以通过还嘴来减掉。之后将(2)式移项(构造常量与非常量之间的不等式以方便检查)

\(D >= M - f1 - f2 + d1 + d2\)

  然后我们选择枚举这两次怼大佬之间的其中一个,则不确定的项即为 \(d2 - f2\) ,因为要求右边的小,所以求这个的最小值之后判断就好了。又因为有之前(1)式的约束,我们在固定了 \(f1\) 后如果能够将 \(f\) 从小到大排序,即可方便判断何时一定不满足(单调递增)。

#include <bits/stdc++.h>
using namespace std;
#define maxn 110
#define ll long long
#define INF 990000000
int n, m, mc, a[maxn], w[maxn];
int ans, maxx, top, B[maxn];
int mark[maxn], f[maxn][maxn];
pair <int, int> S[];
map <int, int> Map[maxn]; struct node
{
int num, v, lev;
}; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} void upmax(int &x, int y) { x = x > y ? x : y; } void DP()
{
for(int i = ; i <= n; i ++)
for(int j = ; j <= mc - a[i]; j ++)
{
upmax(f[i][min(mc, j + w[i])], f[i - ][j + a[i]]); // add blood
upmax(f[i][j], f[i - ][j + a[i]] + ); // do nothing
ans = max(f[i][j], ans);
}
} void BFS(int tot)
{
queue <node> q; q.push((node) {, , });
while(!q.empty())
{
node x = q.front(); q.pop();
if(x.num < tot)
{
q.push((node) {x.num + , x.v, x.lev + });
if(x.lev > && x.v < maxx / x.lev && !Map[x.lev][x.v * x.lev])
{
node y = (node) { x.num + , x.v * x.lev, x.lev};
Map[x.lev][x.v * x.lev] = ;
S[++ top] = make_pair(y.v, y.num); q.push(y);
}
}
}
} int main()
{
n = read(), m = read(), mc = read();
for(int i = ; i <= n; i ++) a[i] = read();
for(int i = ; i <= n; i ++) w[i] = read();
for(int i = ; i <= m; i ++) B[i] = read(), maxx = max(maxx, B[i]);
memset(f, , sizeof(f)); f[][mc] = ; DP();
BFS(ans); sort(S + , S + top + );
for(int i = ; i <= m; i ++)
{
int t = B[i], fans = , fmin = INF;
if(t < ans) { printf("1\n"); continue; }
for(int j = top, k = ; j; j --)
{
while(k <= top && S[k].first + S[j].first <= t)
fmin = min(fmin, S[k].second - S[k].first), k ++;
if(fmin + t - S[j].first + S[j].second <= ans) { fans = ; break; }
if(S[j].first <= t && S[j].second + t - S[j].first <= ans) { fans = ; break; }
}
printf("%d\n", fans);
}
return ;
}

【题解】HNOI2017大佬的更多相关文章

  1. 题解 [AHOI2017/HNOI2017]大佬

    传送门 注意到题面里n很小,有\(n\leq100\) 考虑联系n的实际意义 n是你在大佬手中能活的天数 题面颇富深意 好了不闹了 n很小,对于\(40\%\)的数据,爆搜即可 考场上靠这个骗了40p ...

  2. [AH/HNOI2017]大佬

    题目描述 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你作为一个 OIER,面对这样的事情非常不开心,于 ...

  3. [AH2017/HNOI2017]大佬

    题目描述 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你作为一个 OIER,面对这样的事情非常不开心,于 ...

  4. [HNOI2017]大佬

    参考题解 \(\text{Solution}\) 我们发现5个行为中2操作与其它操作无关,所以我们采用贪心,尽量让多的时间去攻击大佬. 设 \(f[i][j]\) 表示前 \(i\) 天剩 \(j\) ...

  5. bzoj4828 [Hnoi2017]大佬

    Description 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语.你作为一个OIER,面对这样的事情非常 ...

  6. [bzoj4828][Ah/Hnoi2017]大佬

    来自FallDream的博客,未经允许,请勿转载,谢谢. 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你 ...

  7. [AHOI2017/HNOI2017]大佬

    Description: 人们总是难免会碰到大佬.他们趾高气昂地谈论凡人不能理解的算法和数据结构,走到任何一个地方,大佬的气场就能让周围的人吓得瑟瑟发抖,不敢言语. 你作为一个 OIER,面对这样的事 ...

  8. BZOJ4828 AHOI/HNOI2017大佬(动态规划+bfs)

    注意到怼大佬的操作至多只能进行两次.我们逐步简化问题. 首先令f[i][j]表示第i天结束后自信值为j时至多有多少天可以进行非防御操作(即恢复自信值之外的操作).这个dp非常显然.由于最终只需要保证存 ...

  9. HNOI2017大佬

    贼难的一道题 虽然算法都不难,但组合起来就是想不到 首先,最简单的一步,对所有大佬,嘲讽你减的自信值和你做水题回复自信值都是不变的,写个\(dp\),设\(dp[i][j]\)表示第\(i\)天自信值 ...

随机推荐

  1. Post 和 Get的区别?

    Post方法: 1. POST 请求的数据不会被缓存 2. Post请求的内容放置在HTML header中,用户是看不到这个过程的.所以是比较安全的 3. Post请求的数据大小没有限制 Get方法 ...

  2. python 装饰器 生成及原里

    # 装饰器形成的过程 : 最简单的装饰器 有返回值的 有一个参数 万能参数 # 装饰器的作用 # 原则 :开放封闭原则 # 语法糖 :@ # 装饰器的固定模式 #不懂技术 import time # ...

  3. BGP路由控制属性

    控制BGP路由概述: BGP与IGP不同,其着跟点主要在于不同的AS之间控制路由的传播和选择最佳路由 通过修改BGP基本属性可以实现基本的BGP路由控制和最佳路由的选择 引入其他路由协议发现的路由时. ...

  4. UVa Problem 100 The 3n+1 problem (3n+1 问题)

    参考:https://blog.csdn.net/metaphysis/article/details/6431937 #include <iostream> #include <c ...

  5. python2.7入门---运算符 &案例

        已经分享过变量类型的基本概念了,接下来就研究了一下运算符的基础知识.接下来我们就来看一下内容.举个简单的例子 4 +5 = 9 .例子中,4 和 5 被称为操作数,"+" ...

  6. WCF入门三[WCF宿主]

    一.概述 WCF程序必须在宿主上运行,也就是WCF服务必须寄宿在某一个windows的进程中,可以是IIS.控制台程序.窗体程序.WAS以及所有.net程序等程序进程中.在我用VS2013创建WCF服 ...

  7. 小议Android多进程以致Application多次初始化

    最近遇到一个bug,当应用加了多进程后,比如总共进程数为N,会出现在`startService()`时`onStartCommand()`方法会被重复调用`(N-1)`次的奇怪现象. ***## 祸起 ...

  8. Qt 飞机仪表显示

    使用Qt简单谢了一个飞机的一小部分仪表,还没有写完,目前只写了一个界面,不过思想应该是一样的. 效果图如下 其中主要由转速表,和下面的部分数字显示构成 转速表代码 .h文件 #ifndef CONTR ...

  9. Page Object 设计模式介绍

    Page Object 是 Selenium 自动化测试项目开发实践的最佳设计模式之一,Page Object 的主要体现于对界面交互细节的封装,这样可以使测试案例更关注与业务而非界面细节,提高测试案 ...

  10. 调度器&负载均衡调度算法整理

    一.Linux 调度器   Linux中进程调度器已经经过很多次改进了,目前核心调度器是在CFS(Completely Fair Scheduler),从2.6.23开始被作为默认调度器.用作者Ing ...