1. 程式人生 > >●POJ 2828 Buy Tickets

●POJ 2828 Buy Tickets

build scanf ticket strong blank else ont 就是 struct

題鏈:

http://poj.org/problem?id=2828

題解:

線段樹。

逆向考慮這個過程。最後的序列S共有n個元素。

先看最後一個人,如果他插入到第i位,那麽他最終的位置就是當前序列S的第i號位置,然後把這個位置去掉,得到新序列S‘。

再按上面的操作確定倒數第二個人的位置:

如果他插入到第j位,那麽他就在新序列S‘的第j個位置。

。。。。。。以此類推,可以確定出所有人的位置。

可以用線段樹去確定位置。

代碼:

#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 200050
using namespace std;
struct People{
	int p,d;
}P[MAXN];
struct SGT{
	int ls[MAXN<<1],rs[MAXN<<1],siz[MAXN<<1],sz,rt;
	void build(int &u,int l,int r){
		u=++sz; siz[u]=r-l+1;
		if(l==r) return;
		int mid=(l+r)/2;
		build(ls[u],l,mid);
		build(rs[u],mid+1,r);
	}
	void Reset(int n){
		sz=rt=0;
		build(rt,1,n);
	}
	int Modify(int u,int l,int r,int k){
		siz[u]--; if(l==r) return l;
		int mid=(l+r)/2;
		if(k<=siz[ls[u]]) return Modify(ls[u],l,mid,k);
		else return Modify(rs[u],mid+1,r,k-siz[ls[u]]);
	}
}DT;
int ANS[MAXN];
int main(){
	int n;
	while(~scanf("%d",&n)){
		DT.Reset(n);
		for(int i=1;i<=n;i++) scanf("%d%d",&P[i].p,&P[i].d);
		for(int i=n,p;i;i--){
			p=DT.Modify(DT.rt,1,n,P[i].p+1);
			ANS[p]=P[i].d;
		}
		for(int i=1;i<n;i++) printf("%d ",ANS[i]);
		if(n) printf("%d\n",ANS[n]);
	}
	return 0;
}

  

●POJ 2828 Buy Tickets