题目链接:点击打开链接
//hdu5493
//题目大意:给n个人排队,每个人都有身高hi,并且只记得前面或者后面有ki个人比他高,要求身高字典序最小
//大概思路:
// 离线操作;
// 对每个人都相当于有两个位置;
// 对身高排序,给身高矮的人尽量选靠前的位置;
// 相当于找空位,用线段树进行点修改,区间查询
#include <iostream>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define N 100020
using namespace std;
struct stu
{
int h, k;
}s[N];
int sum[N<< 2];
int ans[N], n;
bool cmps(stu a, stu b)
{
return a.h< b.h;
}
void pushup(int k) { sum[k]= sum[k<< 1]+ sum[k<< 1| 1]; }
void build(int l, int r, int k)
{
if(l== r) { sum[k]= 1; return; }
int m= (l+ r)>> 1;
build(l, m, k<< 1);
build(m+ 1, r, k<< 1| 1);
pushup(k);
}
int query(int t, int l, int r, int k)
{
if(sum[k]< t) return -1;
if(l== r) return l;
int m= (l+ r)>> 1, anss;
if(sum[k<< 1]>= t) anss= query(t, l, m, k<< 1);
else anss= query(t- sum[k<< 1], m+ 1, r, k<< 1| 1);
return anss;
}
void update(int p, int l, int r, int k)
{
if(l== r) { sum[k]= 0; return; }
int m= (l+ r)>> 1;
if(p<= m) update(p, l, m, k<< 1);
else update(p, m+ 1, r, k<< 1| 1);
pushup(k);
}
int main()
{
int T; cin >> T;
for(int TT= 1; TT<= T; TT++)
{
scanf("%d", &n);
memset(sum, 0, sizeof(sum));
for(int i= 1; i<= n; i++) scanf("%d%d", &s[i].h, &s[i].k);
sort(s+ 1, s+ n+ 1, cmps);
build(1, n, 1);
int flag= 0;
for(int i= 1; i<= n; i++)
{
int pos1= query(s[i].k+ 1, 1, n, 1), pos2= query(n- s[i].k- i+ 1, 1, n, 1);
int p= min(pos1, pos2);
if(p== -1) { flag= 1; break; } else ans[p]= s[i].h;
update(p, 1, n, 1);
}
printf("Case #%d: ", TT);
if(flag) printf("impossible\n");
else
{
printf("%d", ans[1]);
for(int i= 2; i<= n; i++) printf(" %d", ans[i]);
printf("\n");
}
}
return 0;
}