Hdu 5309 JRY is Fighting 2015 Multi-University Training Contest 2

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{sisi1}(1<i|s|)}, you should find the value of T. We can easily find that if |s|1T=+.

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(1kmin(n,m)) where u1=v1,u2=v2,,uk1=vk1 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(1n500000)m(1m106)k(1k100)
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.
 

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!
Hint
Case 1 : At second 1, hero's HP are 71=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 1110=1, bottle has 3+3=6HP, hero used the bottle, hero's HP are 1+6=7, bottle has 0 HP. At second 4, hero's HP are 72=5, bottle has 3 HP. At second 5, hero's HP are 52=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;
}


發佈了138 篇原創文章 · 獲贊 1 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章