// hdu 5493 Queue 线段树
//
// 解题思路:
//
// 线段树中记录区间的位置的总数.对于第i个人他
// 前面有k个或者后面有k个人,那么插入的位置,在他前面
// 就是k,后面的这样计算,已经插入前i-1个人,则剩下n-(i-1)
// 再-k,再减自己的位置.就是n-i-k.在前面预留n-i-k个位置
// 因为求字典序最小,那么两者求一个min设为v就是啦.然后就是在
// v+1的位置上插入i就行啦,单点更新
//
// 比赛的时候,神犇做出来的,向神犇学习继续加油哟~~~FIGHTING!!!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define For(x,a,b,c) for (int x = a; x <= b ; x += c)
using namespace std;
const int MAX_N = 1e5 + 8;
pair<int,int> p[MAX_N];
int N;
int ans[MAX_N];
struct IntervalTree{
int sit[MAX_N<<2];
int ql,qr;
int v;
#define lson(x) (x<<1)
#define rson(x) (x<<1|1)
void push_up(int ro){
sit[ro] = sit[lson(ro)] + sit[rson(ro)];
}
void build(int ro,int L,int R){
if (L == R){
sit[ro] = 1;
return ;
}
int M = (L + R) >> 1;
build(lson(ro),L,M);
build(rson(ro),M+1,R);
push_up(ro);
}
void update(int ro,int L,int R,int K){
if (L == R){
ans[L] = v;
sit[ro] = 0;
return ;
}
int M = (L + R) >> 1;
if (sit[lson(ro)] >= K) update(lson(ro),L,M,K);
else update(rson(ro),M+1,R,K-sit[lson(ro)]);
push_up(ro);
}
}it;
void input(){
scanf("%d",&N);
it.build(1,1,N);
For(i,1,N,1){
scanf("%d%d",&p[i].first,&p[i].second);
}
sort(p+1,p+N+1);
For(i,1,N,1){
int k = p[i].second;
k = min(k,N-i-k)+1;
if (k <= 0 || k > N - i + 1){
printf(" impossible\n");
return ;
}
it.v = p[i].first;
it.update(1,1,N,k);
}
For(i,1,N,1){
printf(" %d",ans[i]);
}
puts("");
}
int main(){
int t;
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d",&t);
int kase = 1;
while(t--){
printf("Case #%d:",kase++);
input();
}
}
hdu 5493 Queue 线段树
最新推荐文章于 2019-01-15 19:59:48 发布