3709: [PA2014]Bohater 贪心

傻傻的。

看到题目猜是贪心。结果只搞出了加血 > 减血的情况(很显然这种情况下把减血量从下到大排就可以了)。

下面讲一下 减血 > 加血的,顺便给出我的证明。

对于这种情况,网上许多题解都是说把加血从大到下排就可以了。然而蒟蒻我还是不大明白,所以简单证了一下。如果错了,请指正。

设当前血量为 z, 存在i, j 使得 a[i] > a[j]

若先杀掉 j, 比先杀掉 i 优,(或者说存在先杀掉 j,后杀掉 i 能解决的情况而 先杀掉 i, 后杀掉 j 无法满足。)

那么 z - (d[i] - a[i]) <= d[j] (对应先杀掉 i 后杀 j 不能满足), z - (d[j] - a[j]) > d[i] (先杀掉 j,后杀掉 i 能解决)

很显然移项后得 z + a[i] <= d[j] + d[i],  z + a[j] > d[i] + d[j], 又因为 a[j] < a[i], 所以不成立。 所以不存在先杀掉 j,后杀掉 i 能解决的情况而 先杀掉 i, 后杀掉 j 无法满足的情况。

所以把加血从大到小排序后模拟一下吧!

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<queue>
 5 #define rep(i,j,k) for(register int i = j; i <= k; i++)
 6 #define maxn 102333
 7 #define ll long long
 8 using namespace std;
 9
10 inline int read() {
11     int s = 0, t = 1; char c = getchar();
12     while( !isdigit(c) ) { if( c == ‘-‘ ) t = -1; c = getchar(); }
13     while( isdigit(c) ) s = s * 10 + c - 48, c = getchar();
14     return s * t;
15 }
16
17 struct node{ int d, a, t; } nod1[maxn], nod2[maxn];
18 bool cmp1(node a,node b) { return a.d < b.d; }
19 bool cmp2(node a,node b) { return a.a > b.a; }
20 int ans[maxn], top = 0;
21 int main() {
22     int n = read(); ll z = read();
23     int d, a, s1 = 0, s2 = 0;
24     rep(i,1,n) {
25         d = read(), a = read();
26         if( d > a ) {
27             nod2[++s2].d = d, nod2[s2].a = a, nod2[s2].t = i;
28         } else {
29             nod1[++s1].d = d, nod1[s1].a = a, nod1[s1].t = i;
30         }
31     }
32     sort(nod1+1,nod1+1+s1,cmp1);
33     sort(nod2+1,nod2+1+s2,cmp2);
34     rep(i,1,s1) {
35         if( z > nod1[i].d ) {
36             ans[++top] = nod1[i].t;
37             z += nod1[i].a - nod1[i].d;
38         } else {
39             puts("NIE"); return 0;
40         }
41     }
42     rep(i,1,s2) {
43         if( z > nod2[i].d ) {
44             ans[++top] = nod2[i].t;
45             z += nod2[i].a - nod2[i].d;
46         } else {
47             puts("NIE"); return 0;
48         }
49     }
50     puts("TAK");
51     rep(i,1,n) if( i != n ) printf("%d ", ans[i]); else printf("%d\n", ans[i]);
52     return 0;
53 }
时间: 2024-10-23 14:49:03

3709: [PA2014]Bohater 贪心的相关文章

bzoj 3709: [PA2014]Bohater 贪心

code: #include <bits/stdc++.h> #define N 100005 #define LL long long using namespace std; void setIO(string s) { string in=s+".in"; freopen(in.c_str(),"r",stdin); } struct data { LL a,d; int id; data(LL a=0,LL d=0,int id=0):a(a),

【贪心】bzoj 3709:[PA2014]Bohater

3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 653  Solved: 220[Submit][Status][Discuss] Description 在一款电脑游戏中,你需要打败n只怪物(从1到n编号).为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值.任何时候你的生命值都不能降到0(或0以下).请问是否存在一种打怪顺序

BZOJ 3709: [PA2014]Bohater

题目 3709: [PA2014]Bohater Time Limit: 5 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 507  Solved: 163[Submit][Status] Description 在一款电脑游戏中,你需要打败n只怪物(从1到n编号).为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值.任何时候你的生命值都不能降到0(或0以下).请问是否存在一种打怪顺序,使得你可以

【BZOJ】3709: [PA2014]Bohater(贪心)

http://www.lydsy.com/JudgeOnline/problem.php?id=3709 很水的题...但是由于脑洞小..漏想了一种情况.. 首先显然能补血的先杀.. 然后杀完后从补血越多的杀..(这点我之前考虑错了QAQ) 正确性显然........ #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream>

bzoj3709: [PA2014]Bohater 贪心

~~~题面~~~ 题解: 首先有一个比较明显的策略,肯定先要把能带给自己受益的先选完,然后再以最佳状态去打那些会给自己带来损失的怪. 对于前一部分(可以带来受益的怪),显然我们需要先从代价小的打起,因为这样可以把生命值越积越多,打代价大的怪也更容易成功. 那么对于后一部分怎么办呢?我们需要从受益大的打起,为什么? 证明: 假设一个怪的受益为back,代价为cost,那么首先假设我们打完所有怪之后剩下have的生命值,那么have的大小是固定的,不会随着操作顺序而改变,因此我们可以考虑用这个来倒推

[bzoj3709][PA2014]Bohater_贪心

bzoj-3709 PA-2014 Bohater 题目大意:在一款电脑游戏中,你需要打败n只怪物(从1到n编号).为了打败第i只怪物,你需要消耗d[i]点生命值,但怪物死后会掉落血药,使你恢复a[i]点生命值.任何时候你的生命值都不能降到0(或0以下).请问是否存在一种打怪顺序,使得你可以打完这n只怪物而不死掉. 数据范围:$1\le n,Hp_{ori}\le 10^5$,$0\le d_i,a_i\le 10^5$. 想法: 期望找到这样一个顺序是的打完不死掉. 我们把怪物分成两种. 第一

【贪心】bzoj3709 [PA2014]Bohater

把怪分成两类看: 一.回血>损血 则若先杀损血少的再杀损血多的,则为当前这一步提供了更高的可能性.因为血量是单增的,所以尽量用较少的血量去干♂耗血较少的怪物. 二.回血<损血 则若先杀回血多的再杀回血少的,则为下一步提供了更高的可能性.当前这一步的可能性也没有减少,因为即使回血多的损血很多,但是由于此时血量已经是单减的了,所以若此时无法杀掉损血多的,将来也不能. ORZ TimeMachine And ZKY 1 #include<cstdio> 2 #include<ios

bzoj3709 [PA2014]Bohater

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3709 [题解] 打完怪最后的体力是固定的,设为lst 我们考虑回血量>=扣血量的怪,这些肯定优先打,顺序肯定是按照扣血量从小到大打,这一定是最优策略,打不了就是NIE了 接着由于lst固定,我们考虑扣血量>回血量的怪,就相当于从lst开始 每次打一个怪吐出"回血量"这么多的血,增加"扣血量"这么多的血. 于是从后往前,就是按回血量从小到大打,依次判

12月刷题总结

各种被屠...学东西各种慢... QAQ 字符串: sam: [SPOJ]7258. Lexicographical Substring Search(后缀自动机) [SPOJ]1812. Longest Common Substring II(后缀自动机) [BZOJ]2555: SubString(后缀自动机) [BZOJ]3172: [Tjoi2013]单词(后缀自动机) [wikioi]3160 最长公共子串(后缀自动机) lcp: [BZOJ]1014: [JSOI2008]火星人pr