传送门:点击打开链接
题意:n个GT排列在一起,他们有两组,有可能是第0组的,也有可能是第1组的。每个人都有一个能力值。每次第i秒第i个人都会对他前面的另一组的人发起攻击,如果能力值比他低,就会退出游戏。另外还有m个数字Ci,在第Ci秒末尾的时候,前Ci个存活的人的能力都会+1,问最后剩余的人数
思路:很明显可以逆推。用isc[i]表示有多少个Ci等于i,s[i]表示isc在前i个的前缀和。那么会有Max > A[i] + s[Maxid - 1] - s[i - 1],Max表示在第i个的后面的对手里面的能力的最大值,Maxid表示最大值的id,然后变换一下就有Max - s[Maxid - 1] > A[i] - s[i - 1],所以我们只要倒着维护Max - s[Maxid - 1]的最大值就可以了。
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; const int MX = 1e5 + 5; const int INF = 0x3f3f3f3f; struct Data { int val, id; } A[MX]; int isc[MX], s[MX]; int main() { int T, n, m; //FIN; scanf("%d", &T); while(T--) { memset(isc, 0, sizeof(isc)); memset(s, 0, sizeof(s)); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d%d", &A[i].id, &A[i].val); } for(int i = 1; i <= m; i++) { int t; scanf("%d", &t); isc[t]++; } s[0] = 0; for(int i = 1; i <= n; i++) { s[i] = s[i - 1] + isc[i]; } int Max[2] = { -INF, -INF}, ans = 0; for(int i = n; i >= 1; i--) { if(Max[A[i].id ^ 1] > A[i].val - s[i - 1]) { ans++; } Max[A[i].id] = max(Max[A[i].id], A[i].val - s[i - 1]); } printf("%d\n",n - ans); } return 0; }