poj 2828 Buy Tickets (线段树)

/*
http://poj.org/problem?id=2828 这道线段树的题竟然弄了两天,太菜了,后来在队友的讲解下才终于恍然大悟 这道题呢,就是插队,但如果从前往后处理的话,一般方法,每插一个,移动后面的 元素,移动位置,这样会超时,所以 用另一种方法,就是从后往前找,用线段树查找 要插入的位置,(这就是线段树的魅力); 每一个节点记录,l-----r存在几个空位,运用插空的方法,每一次查找,应该插入 的第pos[i]空位; 如 一开始 1 2 3 4 为全为空, 当插入一个 元素到 1号位置 那么 原来的2好空位变为了1好,3变为了2 4->3 */ #include<stdio.h> #define N 200100 struct node { int l; int r; int w; }p[N*3]; int a[N],id,pos[N],val[N]; void build(int x,int l,int r) { p[x].l=l; p[x].r=r; p[x].w=r-l+1; if(r==l)return ; int mid=(l+r)/2; build(x*2,l,mid); build(x*2+1,mid+1,r); } void change(int x,int pos) { p[x].w--; if(p[x].l==p[x].r) { id=p[x].l; return; } if(p[x*2].w>=pos)change(x*2,pos); else { change(x*2+1,pos-p[x*2].w); } } int main() { int n,i; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) { scanf("%d%d",&pos[i],&val[i]); } build(1,1,n); for(i=n;i>=1;i--) { change(1,pos[i]+1); a[id]=val[i]; } for(i=1;i<=n;i++) { if(i==1)printf("%d",a[i]); else printf(" %d",a[i]); } printf("\n"); } }

  

posted @ 2012-04-16 20:56  Szz  阅读(315)  评论(0编辑  收藏  举报