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 }
————————————————