http://poj.org/problem?id=2828
逆向处理,初始有n个空位,我们先处理第n个人,显然第n个人的位置一定再第pos[n]+1个空位上,之后剩下了n-1个空位,再处理第n-1个人,同理他在第pos[n-1]+1个空位上,依此类推。那么我们要解决的问题就成了怎么快速的找到第k个空位,这个问题类似线段树的单点更新
segtree数组的容量原来设置的是2*MAXN,结果WA,后来看吴老师书后改为3*MAXN,然后AC了,200000个节点真的需要这么大的空间?
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<iomanip>
#include<limits>
#include<vector>
#include<algorithm> .
#pragma warning(disable:4996)
using namespace std;
const int MAXN = 200100;
int p[MAXN], v[MAXN], segtree[MAXN * 3], ans[MAXN];
void build(int root, int nstart, int nend)
{
if (nstart == nend) {
segtree[root] = 1;
return;
}
int mid = (nstart + nend) / 2;
build(2 * root + 1, nstart, mid);
build(2 * root + 2, mid + 1, nend);
segtree[root] = segtree[2 * root + 1] + segtree[2 * root + 2];
}
int insert(int root, int nstart, int nend,int index)
{
if (nstart == nend) {
segtree[root]--;
return nstart;
}
int mid = (nstart + nend) / 2, t;
if (segtree[2 * root + 1] >= index) t= insert(2 * root + 1, nstart, mid, index);
else t= insert(2 * root + 2, mid + 1, nend, index - segtree[2 * root + 1]);
segtree[root] = segtree[2 * root + 1] + segtree[2 * root + 2];
return t;
}
int main()
{
int n, p[MAXN], v[MAXN];
while (~scanf("%d", &n))
{
build(0, 0, n - 1);
for (int i = 0; i < n; i++)
scanf("%d%d", &p[i], &v[i]);
for (int i = n - 1; i >= 0; i--)
ans[insert(0, 0, n - 1, p[i] + 1)] = i;
for (int i = 0; i < n - 1; i++)
printf("%d ", v[ans[i]]);
printf("%d", v[ans[n - 1]]);
puts("");
}
}