●POJ 2828 Buy Tickets

Posted *ZJ

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了●POJ 2828 Buy Tickets相关的知识,希望对你有一定的参考价值。

题链:

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的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2828 Buy Tickets

POJ 2828 Buy Tickets

POJ2828 Buy Tickets

POJ2828 Buy Tickets 树状数组

POJ 2828 Buy Tickets

poj2828 Buy Tickets