题目链接:POJ2828
【题意】N个人排队,给出(pi,vi)表示一个价值为vi的人插入第pi个位置后面,求出最后所有人的排列顺序
【分析】这题怎么也想不到用线段树做,找了题解才理解的,如果按照正序一个个插入的话需要N^2的复杂度,肯定不行,然后就需要倒序插入,这样每个人插入的位置就是从左到右第pi个空位所在的位置,这里线段树查询用到了类似splay中的找第K大的方法。
【AC CODE】1500ms
#include <cstdio>
#include <cstring>
#include <cctype>
#include <cmath>
#include <map>
//#include <unordered_map>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,a,n) for(int i = a; i < n; i++)
#define repe(i,a,n) for(int i = a; i <= n; i++)
#define per(i,n,a) for(int i = n; i >= a; i--)
#define clc(a,b) memset(a,b,sizeof(a))
#define id(x,y) (x+y|x!=y)
const int INF = 0x3f3f3f3f, MAXN = 200000+10;
int sum[MAXN<<1], p[MAXN],v[MAXN];
inline void push_up(int x, int y, int m){
sum[id(x,y)] = sum[id(x,m)]+sum[id(m+1,y)];
}
void bulid(int x, int y)
{
if(x == y)
{
sum[id(x,y)] = 1;
return;
}
int m = (x+y)>>1;
bulid(x,m);
bulid(m+1,y);
push_up(x,y,m);
}
int query(int x, int y, int k)//查找第k个空位
{
sum[id(x,y)]--;//顺便跟着路径减掉,也可以另外加一个函数修改
if(x == y) return x;
int m = (x+y)>>1;
if(sum[id(x,m)] >= k) return query(x,m,k);
return query(m+1,y,k-sum[id(x,m)]);
}
int ans[MAXN];
int main()
{
#ifdef SHY
freopen("e:\\1.txt", "r", stdin);
#endif
int n;
while(~scanf("%d%*c", &n))
{
rep(i,0,n) scanf("%d %d%*c", &p[i], &v[i]);
bulid(0,n-1);
per(i,n-1,0)
ans[query(0,n-1,p[i]+1)] = v[i];
printf("%d", ans[0]);
rep(i,1,n) printf(" %d", ans[i]);
putchar('\n');
}
return 0;
}