题目:http://poj.org/problem?id=2828
题意:有n个人插队,给定插队的先后顺序和插在哪个位置还有每个人的val,求插队结束后队伍各位置的val。
线段树里比较简单的题目了,点的更新。。
思想是 从后向前插入,用num存储 每一段剩余的位置。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
const int maxn = + ;
int n, pos[maxn], val[maxn], ans[maxn]; struct node
{
int l, r, num;
}tr[*maxn]; void build(int t, int l, int r) //建树
{
tr[t].l = l; tr[t].r = r;
if(tr[t].l == tr[t].r)
{
tr[t].num = ; //初始每一个剩余的位置为1
return;
}
int mid = (l+r)/;
build(*t, l, mid);
build(*t+, mid+, r);
tr[t].num = tr[*t].num + tr[*t+].num;
}
int query(int p, int t)
{
tr[t].num--; //让对应的段的 剩余数减1
if(tr[t].l == tr[t].r)
return tr[t].l;
if(tr[*t].num >= p) //如果左子树剩余数大于 要插入的位置就往左插入。
return query(p, *t);
else
return query(p - tr[*t].num, *t+);
}
int main()
{
int i, x;
while(~scanf("%d", &n))
{
memset(tr, , sizeof(tr));
build(, , n);
for(i = ; i <= n; i++)
scanf("%d%d", &pos[i], &val[i]); for(i = n; i >= ; i--)
{
x = query(pos[i]+, ); //题目是从0开始的
ans[x] = val[i]; //让返回的位置 对应 val
}
for(i = ; i < n; i++)
printf("%d ",ans[i]);
if(n >= )
printf("%d\n",ans[i]);
}
return ;
}