参考题解

\(\text{Solution}\)

我们发现5个行为中2操作与其它操作无关,所以我们采用贪心,尽量让多的时间去攻击大佬。

设 \(f[i][j]\) 表示前 \(i\) 天剩 \(j\) 血量所能攻击的最多次数,是个很简单的 \(dp\) ,决策就是刷不刷水题, ​\(D​\) 就是最多的时间。

void DP() {
memset(f, -1, sizeof f);
f[0][MC] = 0;
for (int i = 0; i < n; ++ i)
for (int j = 0; j <= MC; ++ j) {
if (f[i][j] == -1) continue;
chkmax(D, f[i][j]);
int t = j - a[i + 1];
if (t < 0) continue;
chkmax(f[i + 1][t], f[i][j] + 1);
t = min(t + w[i + 1], MC);
chkmax(f[i + 1][t], f[i][j]);
}
}

那么现在就是给你很多组询问,询问是否能在 \(D\) 天内击败大佬。

考虑一个二元组 \((x, y)\) 表示达到讽刺值为 \(x\) ,能力值为 \(y\) 的最少天数。

然后这些二元组我们可以从 \((1,0)\) \(bfs\)暴力求。

void Get() {
queue<pii> Q;
Q.push(pii(1, 0));
M[pii(1, 0)] = 0; while (Q.size()) {
pii x = Q.front(); Q.pop();
int now = M[x];
if (vis[x.first])
chkmin(V[x.first], now + 1);
else {//V[x]: 至少到V[x]天讽刺值为x,并且明天可以继续累积
vis[x.first] = 1;
b[++tot] = x.first;
V[x.first] = now + 1;
}
if (now >= D - 1) continue;//明天不能继续累积,只能攻击
if (!M.count(pii(x.first, x.second + 1))) {//升级
M[pii(x.first, x.second + 1)] = now + 1;
Q.push(pii(x.first, x.second + 1));
}
if (x.second > 1 && 1ll * x.first * x.second < maxM &&
!M.count(pii(x.first * x.second, x.second))) {//累积讽刺值
M[pii(x.first * x.second, x.second)] = now + 1;
Q.push(pii(x.first * x.second, x.second));
}
}
}

求出二元组后,对所有二元组按讽刺值排序(第一维),记 \(g[i]\) 为第 \(i\) 个二元组 \(x_i-y_i\) 的值。

考虑不怼大佬,回嘴击败大佬:

if (C < D) return true;

考虑怼一次大佬,需满足有 \(x_i\le C​\) \(\text{and}​\) \(C\le x_i +(d -y_i)=g[i]+d​\)

for (int i = 1; i <= tot; ++ i)
if (C >= x[i] && g[i] >= C - D)
return 1;//怼一次

考虑怼两次大佬,需满足有 \(x_i+x_j\le C\ \text{and}\ C\le x_i+x_j+(d-y_i-y_j)\)

两个指针扫描,由于排好序先保证 \(x_i+x_j\le C\) 然后维护前缀 \(g[i]\) 最大值 \(Mx[i]\)

for (int i = 1; i <= tot; i++) {
if (x[i] > c)
return 0;//如果当前大于c,那么之后必然大于c,不满足条件1,是一个小剪枝
while (tail && x[i] + x[tail] > C)
--tail;//由于x单调,可能的答案在i到tail之间
if (tail && g[i] + Mx[tail] >= C - D)
return 1;
}

这题难就难在将原问题抽离成两个单独的问题,将复杂的问题抽离成一些容易的,比较好处理的问题,会对结题有很大帮助,然后就是要多积累,熟悉经典问题的解法,如本题的讨论怼几次的问题上为了满足条件,运用了双指针扫描 \((two\_pointer)\) 的方法。

\(\text{Source}\)

#include <bitset>
#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <assert.h>
#include <algorithm> using namespace std; #define LL long long
#define debug(...) fprintf(stderr, __VA_ARGS__)
#define GO debug("GO\n") inline int rint() {
register int x = 0, f = 1; register char c;
while (!isdigit(c = getchar())) if (c == '-') f = -1;
while (x = (x << 1) + (x << 3) + (c ^ 48), isdigit(c = getchar()));
return x * f;
} template<typename T> inline void chkmin(T &a, T b) { a > b ? a = b : 0; }
template<typename T> inline void chkmax(T &a, T b) { a < b ? a = b : 0; } const int N = 105;
const int maxM = 1e8 + 5;
const int maxN = 1e6 + 10; #define pii pair<int, int> bitset<maxM> vis;
map<pii, int> M;
map<int, int> V;
int n, m, MC, D, tot, a[N], w[N], b[maxN], f[N][N], g[maxN], Mx[maxN]; void DP() {
memset(f, -1, sizeof f);
f[0][MC] = 0;
for (int i = 0; i < n; ++ i)
for (int j = 0; j <= MC; ++ j) {
if (f[i][j] == -1) continue;
chkmax(D, f[i][j]);
int t = j - a[i + 1];
if (t < 0) continue;
chkmax(f[i + 1][t], f[i][j] + 1);
t = min(t + w[i + 1], MC);
chkmax(f[i + 1][t], f[i][j]);
}
} void Get() {
queue<pii> Q;
Q.push(pii(1, 0));
M[pii(1, 0)] = 0; while (Q.size()) {
pii x = Q.front(); Q.pop();
int now = M[x];
if (vis[x.first])
chkmin(V[x.first], now + 1);
else {
vis[x.first] = 1;
b[++tot] = x.first;
V[x.first] = now + 1;
}
if (now >= D - 1) continue;
if (!M.count(pii(x.first, x.second + 1))) {
M[pii(x.first, x.second + 1)] = now + 1;
Q.push(pii(x.first, x.second + 1));
}
if (x.second > 1 && 1ll * x.first * x.second < maxM &&
!M.count(pii(x.first * x.second, x.second))) {
M[pii(x.first * x.second, x.second)] = now + 1;
Q.push(pii(x.first * x.second, x.second));
}
}
} bool solve() {
int tail = tot, C;
scanf("%d", &C);
if (C < D) return 1; for (int i = 1; i <= tot; ++ i)
if (C >= b[i] and g[i] >= C - D)
return 1; for (int i = 1; i <= tot; ++ i) {
if (b[i] > C) return 0;
while (tail and b[i] + b[tail] > C) tail --;
if (tail and g[i] + Mx[tail] >= C - D) return 1;
}
return 0;
} int main() {
#ifndef ONLINE_JUDGE
freopen("xhc.in", "r", stdin);
freopen("xhc.out", "w", stdout);
#endif
scanf("%d%d%d", &n, &m, &MC);
for (int i = 1; i <= n; ++ i) scanf("%d", a + i);
for (int i = 1; i <= n; ++ i) scanf("%d", w + i); DP(); if (D == 0) {
for (int i = 1; i <= m; ++ i) printf("0\n");
return 0;
} Get();
sort(b + 1, b + 1 + tot);
for (int i = 1; i <= tot; ++ i) {
g[i] = b[i] - V[b[i]];
Mx[i] = max(Mx[i - 1], g[i]);
}
while (m --)
puts(solve() ? "1" : "0");
}

[HNOI2017]大佬的更多相关文章

  1. bzoj4828 [Hnoi2017]大佬

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

  2. [AH/HNOI2017]大佬

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

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

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

  4. [AH2017/HNOI2017]大佬

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

  5. [AHOI2017/HNOI2017]大佬

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

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

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

  7. HNOI2017大佬

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

  8. [AH2017/HNOI2017]大佬(动态规划 搜索)

    /* 神仙yyb 理解题意可以发现 能够对大佬造成的伤害只和你怼了多少天大佬有关, 而且显然天数越多越好 那么我们可以先通过预处理来找出我们最多能够怼多少天大佬 然后我们发现最后我们能怼的血量状态数是 ...

  9. 【题解】HNOI2017大佬

    哎……做了几个小时最后还是没能想到怼大佬的合法性到底怎么搞.写暴力爆搜感觉复杂度爆炸就没敢写 bfs / dfs 一类,后来发现在种种的约束条件下(远小于所给的 \(n, m\))复杂度完全是可以承受 ...

随机推荐

  1. linux 重启 启动 apache服务

    如何使用service  httpd restart,不成功的话,直接去apache文件目录里去找可执行文件,执行启动. 一般apache目录 ./usr/local/httpd/bin ,在bin目 ...

  2. Java中的IO流(四)

    上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...

  3. ubuntu18.04错误配置变量环境导致无法进入系统

    1.问题描述 错误配置环境变量(直接在/etc/profile文件末尾添加了export xxx),关机后一直在登录界面循环无法进入系统. ###环境变量的添加是在原有变量之后以冒号(:)分隔加入,并 ...

  4. zabbix基本监控各指标简解

    监控项目及使用模板 监控http和https: Template App HTTP Service     Template App HTTPS Service 监控cpu,内存,网络等: Templ ...

  5. python小白的初步爬虫

    前序:  最近工作不是很忙,领导突然找我谈话,说是谈话,其实就是分配活呗.果不其然,很快进入正题, 给了我一个网址链接,然后说需要商品的信息...巴拉巴拉.好吧,去做吧. 我当时的内心是崩溃的,pyt ...

  6. Fedora 下面安装FTP服务

    1. yum install vsftpd 2. systemctl disable vsftpd.service 3. systemctl stop vsftpd.service 4. system ...

  7. Java-谈谈对Java平台的理解

    问题 谈谈对 Java 平台的理解 Java是解释执行的 这句话对么 程序的编译与解释有什么区别 Java 平台的了解 Java的主要特点是两个, 编写一次到处运行 Write once, run a ...

  8. 【commons】字符串工具类——commons-lang3之StringUtils

    类似工具见Hutool-StrUtil 一.起步 引入maven依赖 <!-- https://mvnrepository.com/artifact/org.apache.commons/com ...

  9. LeetCode: 57. Insert Interval(Hard)

    1. 原题链接 https://leetcode.com/problems/insert-interval/description/ 2. 题目要求 该题与上一题的区别在于,插入一个新的interva ...

  10. spring-boot、mybatis整合

    一.MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 X ...