题意不说了。思路是将人倒叙插入,线段树各个区间的值代表前面有多少个空位。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <queue>
#include <stack>
#include <math.h>
#include <map>
#include <vector>
#define LL __int64
using namespace std;
const int maxn=200005;
int sum[maxn*4];
int num[maxn*4];
int p[maxn],v[maxn];
void build(int o,int L,int R) //建树过程
{
if(L==R)
{
sum[o]=1; //初始都为1
return;
}
int M=(L+R)>>1;
build(o*2,L,M); //左子树
build(o*2+1,M+1,R); //右子树
sum[o]=sum[o*2+1]+sum[o*2]; //当前区间的和为左右子树的和
}
void update(int o,int p,int w,int L,int R)
{
if(L==R && sum[o]==1) //1表示这个位置没有人
{
sum[o]--;
num[L]=w;
return;
}
int M=(L+R)>>1;
if(p>sum[o*2])
update(o*2+1,p-sum[o*2],w,M+1,R); //注意这里p要减去左子树的值
else
update(o*2,p,w,L,M);
sum[o]=sum[o*2]+sum[o*2+1];
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
build(1,1,n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&p[i],&v[i]);
p[i]++;
}
for(int i=n-1;i>=0;i--)
{
update(1,p[i],v[i],1,n);
}
for(int i=1;i<=n;i++)
{
printf("%d",num[i]);
if(i==n)
printf("\n");
else
printf(" ");
}
}
return 0;
}poj2828(线段树单点更新),布布扣,bubuko.com
原文:http://blog.csdn.net/mfmy_szw/article/details/21192727