poj2828

题意:人们一个一个的来排队并插队,按人到来的顺序给出每个人插队的位置(插在第几个人后面),并告知每个人的id号,输出最终队伍的情况。

分析:可以用线段树,从最后来的一个人开始向来得更早的人遍历,这样pos(插在第几个人后面)的意义就变成了,前面有多少个空位。线段树上每个节点中存储的是当前时刻,该区间有多少空位。

View Code
#include < iostream >
#include
< cstdlib >
#include
< cstring >
#include
< cstdio >
using namespace std;

#define maxn 200005

struct Node
{
Node
* pleft, * pright;
int num, l, r, pos;
}tree[maxn
* 10 ];

struct Item
{
int pos, val;
}f[maxn];

int n, ncount, ans[maxn];

void input()
{
for ( int i = 0 ; i < n; i ++ )
scanf(
" %d%d " , & f[i].pos, & f[i].val);
}

void buildtree(Node * proot, int l, int r)
{
proot
-> num = r - l + 1 ;
proot
-> l = l;
proot
-> r = r;
if (l == r)
{
proot
-> pos = l;
return ;
}
ncount
++ ;
proot
-> pleft = tree + ncount;
ncount
++ ;
proot
-> pright = tree + ncount;
int mid = (l + r) / 2 ;
buildtree(proot
-> pleft, l, mid);
buildtree(proot
-> pright, mid + 1 , r);
}

void ins(Node * proot, int num, int val)
{
proot
-> num -- ;
if (proot -> l == proot -> r)
{
ans[proot
-> pos] = val;
return ;
}
if (num >= proot -> pleft -> num)
ins(proot
-> pright, num - proot -> pleft -> num, val);
else
ins(proot
-> pleft, num, val);
}

void work()
{
for ( int i = n - 1 ; i >= 0 ; i -- )
ins(tree, f[i].pos, f[i].val);
printf(
" %d " , ans[ 0 ]);
for ( int i = 1 ; i < n; i ++ )
printf(
" %d " , ans[i]);
printf(
" \n " );
}

int main()
{
// freopen("D:\\t.txt", "r", stdin);
while (scanf( " %d " , & n) != EOF )
{
input();
buildtree(tree,
0 , n - 1 );
work();
}
return 0 ;
}

你可能感兴趣的:(poj)