机灵点的模拟。
首先是英雄的最优模拟的数组:第一天的最优力量、第二天的最优力量... ( 这样形成的就是一个偏序集合,复杂度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; } }