https://vjudge.net/problem/Gym-101572G
题目大意:
n
n
n支队伍,
m
m
m个事件,每个事件
(
t
,
p
)
(t,p)
(t,p)表示第
t
t
t支队伍完成了一道题目,罚时为
p
p
p,题数越多,排名越靠前,若题数相等,罚时越小,排名越靠前。每次事件发生之后,你都要输出
1
1
1个数字,表示队伍
1
1
1的排名。
思路:离散化+树状数组可做。不过这里采用更简单的一种方法 s e t set set,如果事件 m i m_i mi的 t = 1 t=1 t=1,那么我们更新队伍 1 1 1的排名,并把在它之后的所有元素全部删除;否则我们更新队伍 t t t的数据,如果它的排名大于队伍 1 1 1的排名,就把它放到 s e t set set中,否则不做操作。也就是说 s e t set set中只保留排名在队伍 1 1 1之前的队伍(包括队伍 1 1 1)。那么每次事件发生后的答案就是当前 s e t set set的元素数量。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node
{
int num,p,id;
node(){}
bool operator <(const node& a)const
{
if(num==a.num)
{
if(p==a.p)
return id<a.id;
return p<a.p;
}
return num>a.num;
}
}a[maxn];
set<node> s;
int main()
{
int n,m,t,p;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
a[i].num=a[i].p=0,a[i].id=i;
s.insert(a[1]);
set<node>::iterator it;
while(m--)
{
scanf("%d%d",&t,&p);
if(t==1)
{
s.erase(a[1]);
++a[1].num,a[1].p+=p;
s.insert(a[1]);
it=s.find(a[1]);
s.erase(++it,s.end());
}
else
{
if(a[t]<a[1])
s.erase(a[t]);
++a[t].num,a[t].p+=p;
if(a[t]<a[1])
s.insert(a[t]);
}
printf("%d\n",s.size());
}
return 0;
}