JRY is Fighting
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 104 Accepted Submission(s): 34
Problem Description
Long long ago, there is a hero fighting against the emperor JRY. At the very beginning, the hero has
m
HPs(health-points). There points represent his health - if ever they fall below or equal to zero, the hero will die. In the following
n
seconds, he will be hurt by XXY. At the
i
seconds, his HP will reduce by
hi
. If
hi<0
, it means his HP will increase by
|hi|
.
The hero has a magic bottle which can store HPs. At first, the bottle is empty. Each time after the hero got hurt, the bottle can get k more HPs, and the hero can decide whether he will release the HPs in the bottle. If he does, he will gain the HPs in the bottle and the bottle will be empty.
We define the hero's operating sequence as s , representing that he used the magic bottle at the si -th seconds. |s| represent the times he used, as well as the length of the sequence.
Now, you should maximize the mininum time interval between two adjacent operation. In other words, let T=max{min{si−si−1}(1<i≤|s|)} , you should find the value of T . We can easily find that if |s|≤1 , T=+∞ .
You should give him a plan as an operating sequence s which is right for the hero to survive successfully. The hero is so strict that you should find the lexicographically smallest one.
Sequence u1,u2,⋯,un is lexicographically smaller than sequence v1,v2,⋯,vm , if
n<m and u1=v1,u2=v2,⋯,un=vn , or
there exists an integer k(1≤k≤min(n,m)) where u1=v1,u2=v2,⋯,uk−1=vk−1 and uk<vk all hold.
The hero has a magic bottle which can store HPs. At first, the bottle is empty. Each time after the hero got hurt, the bottle can get k more HPs, and the hero can decide whether he will release the HPs in the bottle. If he does, he will gain the HPs in the bottle and the bottle will be empty.
We define the hero's operating sequence as s , representing that he used the magic bottle at the si -th seconds. |s| represent the times he used, as well as the length of the sequence.
Now, you should maximize the mininum time interval between two adjacent operation. In other words, let T=max{min{si−si−1}(1<i≤|s|)} , you should find the value of T . We can easily find that if |s|≤1 , T=+∞ .
You should give him a plan as an operating sequence s which is right for the hero to survive successfully. The hero is so strict that you should find the lexicographically smallest one.
Sequence u1,u2,⋯,un is lexicographically smaller than sequence v1,v2,⋯,vm , if
n<m and u1=v1,u2=v2,⋯,un=vn , or
there exists an integer k(1≤k≤min(n,m)) where u1=v1,u2=v2,⋯,uk−1=vk−1 and uk<vk all hold.
Input
There are multiple testcases, the sum of
n
is less then
106
.
The first line contains three space-separated integers each, n(1≤n≤500000) , m(1≤m≤106) , k(1≤k≤100) .
The second line contains n space-separated integers, ai(0≤|ai|≤100) .
The first line contains three space-separated integers each, n(1≤n≤500000) , m(1≤m≤106) , k(1≤k≤100) .
The second line contains n space-separated integers, ai(0≤|ai|≤100) .
Output
If the hero can't survive, print "Poor Hero!".
If T=+∞ , print "Poor JRY!".
Otherwise, print three lines:
The first line, an integer, representing the value of T .
The second line, an integer, |s| .
The third line, |s| space-separated intergers, si .
If T=+∞ , print "Poor JRY!".
Otherwise, print three lines:
The first line, an integer, representing the value of T .
The second line, an integer, |s| .
The third line, |s| space-separated intergers, si .
Sample Input
5 7 3 1 -2 10 2 2 2 33 33 -33 -33 1 1 1 1
Sample Output
2 2 1 3 Poor JRY! Poor Hero!HintCase 1 : At second 1, hero's HP are 7−1=6 , bottle has 3 HP, hero used the bottle, hero's HP are 6+3=9 , bottle has 0 HP. At second 2, hero's HP are 9+2=11 , bottle has 3 HP. At second 3, hero's HP are 11−10=1 , bottle has 3+3=6 HP, hero used the bottle, hero's HP are 1+6=7 , bottle has 0 HP. At second 4, hero's HP are 7−2=5 , bottle has 3 HP. At second 5, hero's HP are 5−2=3 . Hero escaped successfully with T=2,s1=1,s2=3 . Case 2 : Anyhow, hero can survive without using the bottle. So T=+∞ . Case 3 : Anyhow, hero's HP will be zero in chamber 1. So he can't survive.题意:一个hero有m HPs值,当他的HPs<=0是会killed。现在有n秒攻击,每一秒会受到一次伤害为a[i](a[i]为负时HPs增加)。他还有一个瓶子,每受到一次攻击瓶子的HPs就会增加k。他可以选择在某时刻使用瓶子的HPs恢复自己的HPs(一次使用完)。 为了能存活下来,可能存在很多递增的S序列。S[i]是使用瓶子恢复HPs的时刻。求一个字典序最小的S序列 ,并且T最大。 T=max{min{Si−Si−1}(1<i≤|S|)} 数据规模: n(1≤n≤500000), m(1≤m≤106), k(1≤k≤100).,ai(0≤|ai|≤100).T=max{min{Si−Si−1}(1<i≤|S|)} 让T尽可能大,那么间隔尽可能大 让S字典序小,Si尽可能早使用 假设在i时刻使用了瓶子,那么使用下一个瓶子前,最远能达到r[i]时刻,r[i]时刻必须使用瓶子,否则r[i]+1时刻会killed。 设dp[i]=max{ Sj+1-Sj | Sj>i } 那么dp[i]=max{min{ j-i , dp[j] } | i<j<r[i] } dp[0]就是T的最大解。 计算S序列。假设当前使用瓶子时刻是t,那么下一时刻min(k | t+T < k && dp[k] >= T ) 时间复杂度:O(n^2) 优化!!#include<iostream> #include<cstdio> #include<cmath> #include<queue> #include<cstring> #include<algorithm> using namespace std; #define sf scanf #define mx 100000000 struct node{ int id,v; //friend bool operator<(node a,node b){return (a.v==b.v)?(a.id>b.id):(a.v>b.v);} bool operator < (const node &a)const { if(a.v==v)return id>a.id; return v<a.v; } }; priority_queue<node> que1,que2; queue<int> que; int n,m,k; int g[1000000],sum[1000000],a[1000000],r[1000000]; int main() { #ifdef ACBang freopen("j.in","r",stdin); freopen("1010.out","w",stdout); #endif // ACBang while(~scanf("%d%d%d",&n,&m,&k)) { while(!que1.empty()) que1.pop(); while(!que2.empty())que2.pop(); for(int i = 1;i<=n;i++) {sf("%d",a+i);sum[i]=sum[i-1]+a[i];} int t = 0; for(int i = 0;i<=n;i++){while(t<=n&&sum[t]<i*k + m) t++;r[i] = t-1;} for(int i = n;i>0;i--) { g[i] = 0; if(r[i] == n) g[i] = mx + i; else { while(!que1.empty()){ node tmp = que1.top(); if(tmp.id>r[i])que1.pop(); else if(tmp.v*2>=g[tmp.id] + i) { que2.push(node{tmp.id,g[tmp.id]-tmp.id}); que1.pop(); } else break; } while(!que2.empty()) { node tmp = que2.top(); if(tmp.id>r[i])que2.pop(); else break; } if(!que1.empty())g[i] = max(g[i],que1.top().v); if(!que2.empty())g[i] = max(g[i],que2.top().v+i); } if(g[i]>i) que1.push((node){i,i}); else que2.push((node){i,g[i]-i}); } for(int i = 1;i<=n;i++)g[i]-=i; g[0] = 0; for(int i = 1;i<=r[0];i++) g[0] = max(g[0],g[i]); if(g[0] > n) puts("Poor JRY!"); else if(!g[0]) puts("Poor Hero!"); else { printf("%d\n",g[0]); int i = 1; while(g[i]!=g[0]) i++; //cout<<T<<":"<<g[1]<<endl; que.push(i); while(g[i]!=mx) { //cout<<i<<":"<<g[i]<<"---"<<endl; int j=i+g[0]; while(g[j]<g[0]) { // cout<<j<<"---"<<g[j]<<" "<<j-i<<endl; // getchar(); j++; } i = j; que.push(i); // cout<<i<<endl; } printf("%d\n",que.size()); while(!que.empty()) { int tmp = que.front(); printf("%d",tmp); que.pop(); if(que.size())printf(" "); else printf("\n"); } } } return 0; }