POJ 2828 Buy Tickets

POJ_2828

    这个题目和POJ_2182很像,我们可以从后往前依次查询,排在p的右边就说明自己是排在第p+1位的,因此,我们可以维护一个线段树,节点值表示当前区间内还有多少个位置,寻找到当前第p+1个位置的所在地时,就把value存进去,然后把这个位置删除,即自底向上更新一遍节点值即可。

#include<stdio.h>
#include<string.h>
#define MAXD 200010
int tree[4 * MAXD], q[MAXD], a[MAXD], b[MAXD], N, M;
void init()
{
int i, j;
for(M = 1; M < N + 2; M <<= 1);
memset(tree, 0, sizeof(tree));
for(i = 0, j = M + 1; i < N; i ++, j ++)
tree[j] = 1;
for(i = M - 1; i; i --)
tree[i] = tree[2 * i] + tree[2 * i ^ 1];
for(i = 0; i < N; i ++)
scanf("%d%d", &a[i], &b[i]);
}
void solve()
{
int i, j, k;
for(i = N - 1; i >= 0; i --)
{
k = a[i] + 1;
for(j = 1; j < M;)
{
if(tree[2 * j] >= k)
j <<= 1;
else
{
k -= tree[2 * j];
j = (j << 1) + 1;
}
}
q[j - M - 1] = b[i];
for(; j ^ 1; j >>= 1)
tree[j] --;
}
for(i = 0; i < N; i ++)
{
if(i)
printf(" ");
printf("%d", q[i]);
}
printf("\n");
}
int main()
{
while(scanf("%d", &N) == 1)
{
init();
solve();
}
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2226724.html