poj 2828 buy tickets

题目大意:

一些人要排队,开始时队为空

给定一些数对 表示这些人的状态

这些人按数对的顺序准备入队

其中每个数对第一个数a表示这个人来的时候站在当前队伍中a个人的后面,a=0时站在队伍最前面

第二个数b表示这个人的编号

求最终队伍的顺序,即依次输出他们的编号

思路:

首先可知最后一个人进入时 数对的b即为他的最终位置

则我们可以逆序插队

然后把已经进队的忽略

可以用线段树nlogn,维护一下L—R的空位置

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<vector>
 9 #include<set>
10 #include<stack>
11 #define inf 2147483611
12 #define ll long long
13 #define MAXN 201010
14 using namespace std;
15 inline int read()
16 {
17     int x=0,f=1;
18     char ch;ch=getchar();
19     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
20     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
21     return x*f;
22 }
23 struct data
24 {
25     int w,l,r;
26 }tr[MAXN*3];
27 int pos[MAXN],val[MAXN],n,ans[MAXN],now;
28 void build(int k,int l,int r)
29 {
30     tr[k].l=l,tr[k].r=r,tr[k].w=r-l+1;
31     if(l==r) return ;
32     int m=(l+r)>>1;
33     build(k<<1,l,m);build(k<<1|1,m+1,r);
34     return ;
35 }
36 void update(int k,int p)
37 {
38     tr[k].w--;
39     int l=tr[k].l,r=tr[k].r;
40     if(l==r) {now=l;return ;}
41     if(tr[k<<1].w>=p) update(k<<1,p);
42     else
43     {
44         p-=tr[k<<1].w;
45         update(k<<1|1,p);
46     }
47 }
48 int main()
49 {
50     while(scanf("%d",&n)!=EOF)
51     {
52         build(1,1,n);
53         for(int i=1;i<=n;i++)
54             pos[i]=read(),val[i]=read();
55         for(int i=n;i>=1;i--) {update(1,pos[i]+1);ans[now]=val[i];}
56         for(int i=1;i<=n;i++) printf("%d ",ans[i]);
57         printf("\n");
58     }
59 }
View Code

 

posted @ 2017-10-02 13:09  jack_yyc  阅读(126)  评论(0编辑  收藏  举报