poj2828 Buy Tickets

树状数组找第k大

倒着来,取了的排名就去掉。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,s[410000];
int lowbit(int x){return x&-x;}
void change(int x,int k)
{
    while(x<=405000)
    {
        s[x]+=k;
        x+=lowbit(x);
    }
}
int Bin[30];
int findk(int k)
{
    int pos=0,sum=0;
    for(int i=22;i>=0;i--)
        if(pos+Bin[i]<=n&&sum+s[pos+Bin[i]]<k)
            sum+=s[pos+Bin[i]], pos+=Bin[i];
    pos++;
    return pos;
}

int pos[210000],id[210000],as[210000];
int main()
{
    Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2;
    
    while(scanf("%d",&n)!=EOF)
    {
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++)
            scanf("%d%d",&pos[i],&id[i]), pos[i]++, change(i,1);
        for(int i=n;i>=1;i--)
        {
            int k=findk(pos[i]);
            as[k]=id[i], change(k,-1);
        }
        for(int i=1;i<=n;i++)printf("%d ",as[i]);
        printf("\n");
    }
    return 0;
}

posted @ 2018-08-06 16:40  AKCqhzdy  阅读(103)  评论(0编辑  收藏  举报