poj 2828 Buy Tickets(线段树)

题目链接:http://poj.org/problem?id=2828

线段树单点更新问题。

从后往前插入,因为最后一个插入某位置的数是确定的。

之后每个节点用sum记录该区间的空位置数,

如果左区间空位置数比要插入位置大,更新左区间,否则更新右区间,并且pos要减去左区间空位置数。

(感觉想到这一点就会比较容易,否则有一种无从下手的感觉。。。)

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

const int INF=0x3f3f3f3f;
const int maxn=200010;
int T,n;
int sum[maxn],sequence[maxn];

struct Point{
	int pos;
	int val;
}p[maxn];

struct segTree{
	int l;
	int r;
	int sum;
}node[3*maxn];

void PushUp(int id){
	node[id].sum=node[id<<1].sum+node[id<<1|1].sum;
}

void build(int id,int l,int r){
	node[id].l=l;
	node[id].r=r;
	node[id].sum=r-l+1;//表示该区间空位置数
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
}

void Update(int pos,int val,int l,int r,int id){
	if(l==r){
		sequence[l]=val;
		node[id].sum=0;
		return ;
	}
	int mid=(l+r)>>1;
	if(pos<=node[id<<1].sum)
		Update(pos,val,l,mid,id<<1);
	else
		Update(pos-node[id<<1].sum,val,mid+1,r,id<<1|1);
	PushUp(id);
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
#endif
    while(~scanf("%d",&n)){
    	build(1,1,n);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d",&p[i].pos,&p[i].val);
    	memset(sum,0,sizeof(sum));
    	for(int i=n;i>=1;i--)
    		Update(p[i].pos+1,p[i].val,1,n,1);
    	for(int i=1;i<=n;i++)
    		printf("%d%c",sequence[i],i==n?'\n':' ');
    }
    return 0;
}


你可能感兴趣的:(poj 2828 Buy Tickets(线段树))