题意:
从前,有n只萌萌的GT,他们分成了两组在一起玩游戏。他们会排列成一排,第i只GT会随机得到一个能力值bi。在第i秒的时候,第i只GT可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的GT。 为了使游戏更加有趣,GT的首领GTW会发功m次,第i次发功的时间为ci,则在第ci秒结束后,b1,b2,...,bci都会增加1。 现在,GTW想知道在第n秒之后,会有几只GT存活下来。
这个题就是凸显出了自己智商低的一个典范,我一直在想前面的怎么加,不能一直循环相加,后来终于想明白了可以先把前面的统一加起来,是不影响后面的,因为在当前那秒的时候,你只需要知道前面的数是多少就是了,你当前这个数加了多少,你前面的数就该加多少,所以不影响。我只需要倒着走就行了。
后来还是没有搞出来,看了官方题解,我就发现我是傻了,都快要做出来了。他有一个转换,其实不算和,就算减的,前面都加1,相当于后面都减一,我就可以顺着做了。郁闷
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#include<vector>
#include<set>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int a[50005];
int b[50005];
int c[50005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
priority_queue<int,vector<int>,greater<int> >q1;//相当于从小到大
priority_queue<int,vector<int>,greater<int> >q0;<span style="font-family: Arial, Helvetica, sans-serif;">//相当于从小到大</span>
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d%d",&a[i],&b[i]);
memset(c,0,sizeof(c));
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
c[--x]++;
}
int cnt=0;
int ans=0;
for(int i=0;i<n;i++)
{
b[i]-=cnt;减去之前的发功次数
printf("%d %d\n",b[i],cnt);
cnt+=c[i];//累加当前是否发功,发功几次
if(a[i]==0)//检查当前他可以打死不是和他一个队伍,并且比他小的
{
while(!q1.empty()&&q1.top()<b[i])
{
//printf("%d\n",q1.top());
ans++;//记下个数
q1.pop();
}
q0.push(b[i]);
}
else
{
while(!q0.empty()&&q0.top()<b[i])
{
//printf("%d\n",q0.top());
ans++;
q0.pop();
}
q1.push(b[i]);
}
}
printf("%d\n",n-ans);
}
}