1 4 3 0 3 1 2 0 3 1 1 1 3 4
3HintAfter the first seconds,$b_1=4,b_2=2,b_3=3,b_4=1$ After the second seconds,$b_1=4,b_2=2,b_3=3,b_4=1$ After the third seconds,$b_1=5,b_2=3,b_3=4,b_4=1$,and the second GT is annihilated by the third one. After the fourth seconds,$b_1=6,b_2=4,b_3=5,b_4=2$ $c_i$ is unordered.
题意:n个GT排列在一起,他们有两组,有可能是第0组的,也有可能是第1组的。每个人都有一个能力值。每次第i秒第i个人都会对他前面的另一组的人发起攻击,如果能力值比他低,就会退出游戏。另外还有m个数字Ci,在第Ci秒末尾的时候,前Ci个存活的人的能力都会+1,问最后剩余的人数
思路:正向去暴力肯定会超时, 但倒着看的话,前面加的总和C 就相当于把后面的数减去C (因为前面加数的时刻 是在判断第i个数是否可以清除前面数 之前的)。
只需记录第i个数该减去多少就行了。然后寻找最大值进行维护更新。
#include<bits/stdc++.h> using namespace std; struct node { int id,val; }p[100000]; int b[100000]; int st[100000]; int main() //逆向思维,倒着判断最大值是否比前面的要大,是同族就更新,不是就num--; { //此处的最大值是原值减去前面的值要长的值数(前面的加1 就等价后面的数减1 ) int T,n,m; while(~scanf("%d",&T)) { while(T--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&p[i].id,&p[i].val); } memset(b,0,sizeof(b)); for(int i=0;i<m;i++) { int t; scanf("%d",&t); t++; //t秒之后 b[t]++; //后面要减少的值 } st[0]=0; for(int i=1;i<=n;i++) { st[i]=st[i-1]+b[i]; //第i个值要减少的值 } //for(int ) int Max1=-1,Max2=-1,num=n; for(int i=n;i>=1;i--) { int tt=p[i].val-st[i]; if(p[i].id==0) { if(Max2>tt) num--; if(Max1<tt) Max1=tt; } else { if(Max1>tt) num--; if(Max2<tt) Max2=tt; } } printf("%d\n",num); } } return 0; } 1 3 3 1 1 0 1 1 1 3 3 3 输出 3
#include<bits/stdc++.h> using namespace std; int a[100000],b[100000]; int v[100000]; int main() { int T; while(~scanf("%d",&T)) { while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); } memset(v,0,sizeof(v)); for(int i=0;i<m;i++) { int t; scanf("%d",&t);t++; v[t]++; } multiset<int>x,y; multiset<int>::iterator it; int del=0; for(int i=1;i<=n;i++) { del+=v[i]; b[i]-=del; if(a[i]) { x.insert(b[i]); it=y.upper_bound(b[i]); //会把相同的也给删了 y.erase(y.begin(),it); } else { y.insert(b[i]); it=x.upper_bound(b[i]); x.erase(x.begin(),it); } } printf("%d\n",x.size()+y.size()); } } return 0; } 1 3 3 1 1 0 1 1 1 3 3 3 输出 1