题目大意:
一些人要排队,开始时队为空
给定一些数对 表示这些人的状态
这些人按数对的顺序准备入队
其中每个数对第一个数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(" "); 58 } 59 }