CodeForces-1257D (貪心+雙指針)

題意

https://vjudge.net/problem/CodeForces-1257Dios

你須要操做m個英雄去戰勝n只怪物,每一個英雄的力量值爲pi,能夠戰勝si只怪物;每隻怪物的力量值爲ai。c++

當新的一天開始時,你能夠選擇其中1個英雄去打怪。若在以前已有k只怪物被戰勝,這個英雄將挑戰第k+1只怪物,此時有兩種狀況:數組

1.英雄力量≤怪物力量,則英雄撤退,這一天結束。spa

2.英雄力量>怪物力量,怪物被戰勝。繼續挑戰下一隻怪物。當n只怪物所有被戰勝,或該英雄已戰勝的怪物數量=si時,這一天結束。.net

你的任務是計算出戰勝全部怪物所須要的最小天數。指針

思路

最簡單的想法就是用si大的儘量多打。blog

維護每一個耐力值si對應的力量最大的英雄,由於相等耐力值狀況下確定是選力量最大的要好。ci

再維護上面數組的後綴最大值,這個其實就是耐力值少的也能夠(注意是能夠!不是必定)用耐力值大的代替,好比對於耐力值i,i+1,若是i+1的力量大於i,那麼徹底能夠用i+1代替i去打,由於耐力值比i大。get

而後用雙指針求解,當前遍歷到第i個怪物,用j往右邊延伸,看最遠能打到哪一個怪物,這裏要實時記錄這一段怪物力量的最大值,若是v[j-i+1]>=mx (v是上述處理完後綴最大值後的數組),那麼就能夠延伸,v[j-i+1]表示耐力值爲j-i+1~n(這一段的耐力值大於mx的英雄均可以使用)的最大英雄力量值。it

代碼

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=200005;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
int a[N],v[N];
int main()
{
    std::ios::sync_with_stdio(false);
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            v[i]=0;
        }
        int m;
        cin>>m;
        for(int i=1;i<=m;i++)
        {
            int p,s;
            cin>>p>>s;
            v[s]=max(v[s],p);
        }
        for(int i=n-1;i>=1;i--)
        {
            v[i]=max(v[i],v[i+1]);
        }
        int i=1,j,ans=0,flag=0;
        while(i<=n)
        {
            if(a[i]>v[1])
            {
                flag=1;
                break;
            }
            j=i;
            int mx=a[i];
            while(j<=n&&v[j-i+1]>=mx)
            {
                j++;
                mx=max(mx,a[j]);
            }
            ans++;
            i=j;
 //           cout<<i<<" "<<ans<<endl;
        }
        if(flag)
            cout<<-1<<endl;
        else
            cout<<ans<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索