题意 两组一共n个同学排成一行,每个同学有个分值,有m次操作每次将1到mi的同学分值加一,每个同学可以消灭排在他前面不同组且分值低于他的同学,问一个有多少同学没消灭了
首先不考虑m次操作,每个同学有没有消灭取决于他后面的同学有没有比他分值大且不同组的。可以发现从后面开始遍历,存下来两组的最大值就可以。
下面看m次操作,可以想出来,对于一个同学,消灭他的是后面的同学,后面的同学消灭他的时候这个操作已经进行过了,所以可以直接先把操作都进行了,对区间操作就要用到差分
#include<iostream> using namespace std; struct node { int idx,num; }a[50010]; int main() { int t; cin>>t; while(t--) { int kill[100010]={0},cha[500100]={0}; int n,m,max0=0,max1=0; cin>>n>>m; for(int i=1;i<=n;i++) { int team,num; cin>>team>>num; if(team==0)a[i].num=num,a[i].idx=0; else a[i].num=num,a[i].idx=1; } cha[1]=1; while(m--) { int r; cin>>r; cha[1]++; cha[r+1]--; } for(int i=1;i<=n;i++)cha[i]+=cha[i-1]; for(int i=1;i<=n;i++)a[i].num+=cha[i]; for(int i=n;i>=1;i--) { if(a[i].idx==0) { if(a[i].num<max1)kill[i]=1; max0=max(max0,a[i].num); } else { if(a[i].num<max0)kill[i]=1; max1=max(max1,a[i].num); } } int ans=n; for(int i=1;i<=n;i++) if(kill[i])ans--; cout<<ans<<endl; } }