机灵点的模拟。
首先是英雄的最优模拟的数组:第一天的最优力量、第二天的最优力量... ( 这样形成的就是一个偏序集合,复杂度O(n+m) ,因为耐力不是很大,所以可以ac)
其次是要维护一个rmq,否则会犯了比赛中的错误。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+500;
//要筛选出一个有用的偏序集合的时候,貌似是排序然后单调栈是最好理解的。
//在这题中,因为维度s的取值范围足够小,可以不进行排序而使用dp来进行转移,
//具体做法就是在每个耐力值上打上最大的pi标记,然后从n向1传递pi,
//这样形成的就是一个偏序集合,复杂度O(n+m)。
int a[maxn],b[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
int n,m;
while(T--){
cin>>n;
for(int i=1; i<=n; i++){
cin>>a[i];
}
cin>>m;
//int p[maxn]; //p是力量数组,下标是耐力,值是力量,这样就可以扫一遍处理出各种英雄的使用情况
//利用了数组下标上升自动排序的特性
// memset(p, -1, sizeof(p));
vector<int> p(n+2);
int pi,si;
for(int i=1; i<=m; i++){
cin>>pi>>si;
p[ si ] = max(p[ si ], pi);
}
for(int i=n-1; i>=1; i--){
p[i] = max(p[i], p[i+1]);
}
int i=1,rmq = -1,ans=0,cnt=1;
while(i <= n){
rmq = max(rmq, a[i]);
if(p[cnt] < rmq){
if(p[1] < rmq){
ans = -2;
break;
}
rmq = -1;
cnt = 0;
++ans;
--i;
}
++cnt;
// cout<<"cnt="<<cnt<<" rmq="<<rmq<<endl;
++i;
}
cout<<ans+1<<endl;
}
}
来源:https://www.cnblogs.com/-Zzz-/p/11892587.html