POJ:2828 Buy Tickets(线段树)

思路真的很奇妙。

从后往前,pos的意义是此时该人前面的空位。

这样用线段树寻找第k个元素即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define ll  long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN  200005
#define LEN 222222<<2
using namespace std;
int num[MAXN],val[MAXN],arr[MAXN];
struct Segment_Tree
{
private :
    int sum[LEN],sz;
    void pushup(int o)
    {
        sum[o]=sum[o<<1]+sum[o<<1|1];
    }
    int myquery(int o,int L,int R,int v)
    {
        if(L==R)
        {
            sum[o]--;
            return L;
        }
        int M=(L+R)>>1;
        int p;
        if(v<=sum[o<<1]) p=myquery(o<<1,L,M,v);
        else  p=myquery(o<<1|1,M+1,R,v-sum[o<<1]);
        pushup(o);
        return p;
    }
public:
    void init(int n)
    {
        sz=n;
    }
    void build(int o,int L,int R)
    {
        sum[o]=R-L+1;
        if(L==R)  return ;
        else
        {
            int M=(L+R)>>1;
            build(o<<1,L,M);
            build(o<<1|1,M+1,R);
        }
    }
    int  query(int p)
    {
        return myquery(1,1,sz,p);
    }
};
Segment_Tree tree;
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1; i<=n; ++i)
            scanf("%d%d",&num[i],&val[i]);
        tree.init(n);
        tree.build(1,1,n);
        for(int i=n; i>=1; --i)
        {
            int pos=tree.query(num[i]+1);
            arr[pos]=val[i];
        }
        for(int i=1; i<=n; ++i)
            if(i==1) printf("%d",arr[i]);
            else printf(" %d",arr[i]);
        printf("\n");
    }
    return 0;
}


 

你可能感兴趣的:(线段树)