2017-2018 ACM-ICPC, NEERC Problem G Galactic Collegiate Programming Contest(树状数组)

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值