题意:火车站有n个人排队,他们是按顺序到达的,但是他们乱插队。每个人有两个值pos[i]和val[i]。比如现在第5个人来了,他的pos[5]值为3,那么他就会插队到当前第3个人位置的后面(第0个人是售票窗口)。依次给出所有人的pos和val值,要你最终按所有人的位置顺序输出val值。
思路:维护一颗线段树,该树的叶子结点初始值为1,表示这个位置可以占用,当确定一个人的位置的时候就把那个值变成0.显然如果从前往后推的话很困难,每下一个人的插入又会改变前面的人的位置,所以呢我们从后往前插入,比如最后一个人的位置就肯定是固定的了,那么固定完这个位置之后不管他,倒数第二个人的位置也一定是固定的了。
Trick:用G++提交超时了...用C++过了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 200000+100;
#define lson i*2,l,m
#define rson i*2+1,m+1,r
struct Node
{
int p,v;
}node[maxn];
int val[maxn*4];
int sum[maxn*4];
int cnt,n;
void PushUp(int i)
{
sum[i] = sum[i*2]+sum[i*2+1];
}
void build(int i,int l,int r)
{
if (l==r)
{
sum[i]=1;
return;
}
int m = (l+r)/2;
build(lson);
build(rson);
PushUp(i);
}
void update(int p,int v,int i,int l,int r)
{
if (l==r)
{
if (sum[i])
{
sum[i]=0;
val[i]=v;
}
return;
}
int m = (l+r)/2;
if (p<=sum[i*2])
update(p,v,lson);
else
update(p-sum[i*2],v,rson);
PushUp(i);
}
void print(int i,int l,int r)
{
if (l==r)
{
cnt++;
printf("%d",val[i]);
if (cnt<n)
printf(" ");
else
printf("\n");
return;
}
int m = (l+r)/2;
print(lson);
print(rson);
}
int main()
{
while (scanf("%d",&n)!=EOF && n)
{
cnt = 0;
build(1,1,n);
for (int i = 1;i<=n;i++)
{
scanf("%d%d",&node[i].p,&node[i].v);
node[i].p++;
}
for (int i = n;i>=1;i--)
{
update(node[i].p,node[i].v,1,1,n);
}
print(1,1,n);
}
}