ccpc哈尔滨站前在网吧的小练习…其实做了一半就去吃饭了
题意
http://codeforces.com/gym/101572/attachments
宇宙acm比赛,n个队(1e5),m个事件(1e5)。每次事件,代表某个队伍做出一道题。给出这个队的编号和这题的罚时。排名按照ac数多的排名靠前,相同ac数罚时少的靠前来定。每次操作输出一次第1个队的排名
思路
把所有出现过的状态(ac数,罚时)存下来,离散化一下。这样就能存某个状态的出现次数。离散化的时候按排名要求排序。这样就可以查询到比1号队伍当前状态排名靠前的有多少人
比如样例。第3个操作的时候,出现过(1,7) (1,5) (1,6)。那么查询(1,6)前面有多少只队,然后+1。第4个操作,在(1,6)处–,在(2,15)处++。然后查询(2,15)前面有,多少点,再+1
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdio>
using namespace std;
int n,m, sz;
const int maxn = 1e5+10;
int bit[maxn];
struct node{
int ac, pe;
node(){
ac=0;pe=0;
}
node(int _ac,int _pe){
ac=_ac;pe=_pe;
}
bool operator < (const node &n){
if(ac>n.ac) return true;
else if(ac < n.ac) return false;
else{
return pe < n.pe;
}
}
bool operator == (const node &n){
return ac==n.ac && pe==n.pe;
}
};
int lowbit(int x){
return x&(-x);
}
void add(int pos,int x){
int i=pos;
while( i <=1e5+2){
bit[i]+=x;
i+=lowbit(i);
//cout<<i<<endl;
}
}
int sum(int pos){
int sum=0;
while(pos>0){
sum += bit[pos];
pos-= lowbit(pos);
}
return sum;
}
node a[maxn], b[maxn],all[maxn];
node query[maxn];
int getid(node n){
return lower_bound(all+1,all+sz+1,n) - all;
}
int main(){
//freopen("data.txt","r",stdin);
memset(bit,0,sizeof(bit));
scanf("%d%d",&n,&m);
int x,y;
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
query[i]=node(x,y);
a[x].ac++;a[x].pe+=y;
all[i]=a[x];
}
all[m+1] = node(0,0);
sort(all+1,all+m+2);
//是这样离散化来着吗
sz = unique(all+1,all+m+2) - (all+1);
// cout<<sz<<endl;
// for(int i=1;i<=sz;i++){
// cout<<getid(all[i])<<endl;
// cout<<all[i].ac<<" "<<all[i].pe<<endl;
// }
for(int i=1;i<=m;i++){
x=query[i].ac,y=query[i].pe;
// cout<<x<<" "<<y<<endl;
if(b[x].ac!=0){
add(getid(b[x]),-1);
}
b[x].ac++;b[x].pe+=y;
//cout<<getid(b[x]);
add(getid(b[x]),1);
//cout<<"hhh"<<endl;
int id =getid(b[1]) - 1;
// cout<<id<<endl;
if(id==0) printf("1\n");
else {
//cout<<"hhh"<<endl;
printf("%d\n",sum(id)+1);
//cout<<"hhh"<<endl;
}
}
return 0;
}