题目
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5493
题目来源:2015合肥网络赛第四题
简要题意: N 个人每个人有高度
hi ,每个人高度不同
已知向前数或向后数比第 i 个人高的人为ki ,重新构建队列。数据范围: T⩽103;1⩽N⩽105;1⩽hi⩽109;0⩽ki⩽N−1
题解
首先从小到大排序是肯定的,排序后第 i 个人有
N−i 个比他高的。由于要字典序最小则应该贪心让小的靠前,应该取 k=min(N−i−k,k)
此时 k<0 就是impossible的情况。
再考虑如何对数时间求解,此处需要使用数据结构。
维护一个树状数组保存之前的数的位置情况,求出一个位置之前有多少位置插入了数。
设 pos 为当前位置, cnt 为 sum(pos) 即当前位置及之前插入的数的个数。
由于所有之前插入的数一定是比当前位置小的,所以 pos−cnt 就是 pos 及之前的空位总数。
如果 pos−cnt>k 则我们在 pos 及之后可以找到位置插入。
上述位置中最小的位置就是我们要插入元素的位置了。
找位置的时候直接遍历复杂度不够,需要写一个二分。
然后只需要不断维护树状数组并且插入元素就能构造出队列了。
实现
由于 hi 比较大,所以在实现的时候要对高度离散化。
赛后补题的时候脑残了,直接在输入的时候取 ki 的 min 了。
然后实际上肯定是要排序了才能这么做的。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 100000+5;
struct BIT {
int tree[N] ;
int lowbit(int x) {
return x&(-x);
}
void add(int x, int add, int n) {
for (; x <= n; x += lowbit(x)) {
tree[x] += add;
}
}
int sum(int x) {
int s = 0;
for (; x > 0; x -= lowbit(x)) {
s += tree[x];
}
return s;
}
void clear() {
memset(tree, 0, sizeof tree);
}
};
BIT tree;
PII a[N];
int res[N];
int get(int x, int n) {
return n-tree.sum(x);
}
int bSearch(int n, int k) {
int l = 1, r = n, mid, x, ans = -1;
while (l <= r) {
mid = (l+r)>>1;
x = get(mid, mid);
if (x > k) {
r = mid-1;
ans = mid;
} else {
l = mid+1;
}
}
return ans;
}
int main() {
int t, cas = 1, n;
scanf("%d", &t);
while (t--) {
tree.clear();
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d%d", &a[i].fi, &a[i].se);
}
sort(a+1, a+n+1);
bool flag = false;
for (int i = 1; i <= n; i++) {
a[i].se = min(a[i].se, n-i-a[i].se);
if (a[i].se < 0) {
flag = true;
break;
}
int pos = bSearch(n, a[i].se);
tree.add(pos, 1, n);
res[pos] = a[i].fi;
}
printf("Case #%d: ", cas++);
if (flag) {
puts("impossible");
} else {
for (int i = 1; i <= n; i++) {
printf("%d%c", res[i], i==n ? '\n' : ' ');
}
}
}
return 0;
}