题意:有n个人陆续来到一个队列里排队(插队),第i个来的人插入到pos[i]位置中,问最后的队列情况。
思路:线段树。很赞的一道题。从最后一个人往前插,这样pos的意义就变成了,前面有多少个空位。线段树上每个节点中存储的是当前时刻,该区间有多少空位。线段树的应用真的很广泛。
源代码:(8644K, 1516MS)
#include<iostream>
using namespace std;
const int MAX = 200005;
struct{
int l, r, w;
}node[3*MAX];
int id, pos[MAX], val[MAX], ans[MAX];
void BuildTree(int left, int right, int u){
node[u].l = left;
node[u].r = right;
node[u].w = right - left + 1; // w记录这个区间有多少的空位。
if(left < right){
BuildTree(left, (left+right)>>1, u<<1);
BuildTree(((left+right)>>1)+1, right, (u<<1)+1);
}
}
void updata(int pos, int u){
node[u].w --; // 这个区间增加了一人,区间空位-1。
if(node[u].l == node[u].r){
id = node[u].l; return;
}
if(node[u<<1].w >= pos) updata(pos, u<<1);
else{
pos -= node[u<<1].w;
updata(pos, (u<<1)+1);
}
}
int main(){
int n, i;
while(scanf("%d", &n) != EOF){
BuildTree(1, n, 1);
for(i = 1; i <= n; i ++)
scanf("%d%d", &pos[i], &val[i]);
for(i = n; i >= 1; i --){
updata(pos[i]+1, 1);
ans[id] = val[i];
}
for(i = 1; i <= n; i ++)
printf("%d ", ans[i]);
printf("\n");
}
return 0;
}