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