题目链接:https://cn.vjudge.net/problem/POJ-2828
题目大意
有n个数,依次给出每个数插在第几个数后面,以及这个数是多少,求最终的序列。
分析
最后插入的位置肯定是确定的,所以从后往前看,假设x插在第i个数后面,那么x前面一定有i个空格,二分找到这个位置,然后将这个位置剔除,以此类推。
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 2e5+10;
int n, c[N], ans[N];
struct people{
int id, w;
}p[N];
int lowbit(int x)
{
return x & (-x);
}
void updata(int x, int w)
{
while(x < N)
{
c[x] += w;
x += lowbit(x);
}
}
int ask(int x)
{
int sum = 0;
while(x)
{
sum += c[x];
x -= lowbit(x);
}
return sum;
}
int er(int k)
{
int l = 1, r = n;
while(l <= r)
{
int mid = (l + r) >> 1;
if(ask(mid) >= k)
r = mid - 1;
else
l = mid + 1;
}
return l;
}
int main()
{
while(~scanf("%d", &n))
{
for(int i = 1; i <= n; i++)
scanf("%d %d", &p[i].id, &p[i].w);
memset(c, 0, sizeof c);
for(int i = 1; i <= n; i++)
updata(i, 1);
for(int i = n; i >= 1; i--)
{
int x = er(p[i].id + 1);//前面有p[i].id个空格,加上自己,一共p[i].id+1个
ans[x] = p[i].w;
updata(x, -1);
}
for(int i = 1; i <= n; i++)
printf("%d%s", ans[i], i == n ? "\n" : " ");
}
return 0;
}