您的位置:首页 > 其它

hdu 5493(线段树)

2015-09-27 17:47 218 查看
题意:有n个人,每个人的身高和左边或右边比自己高的人的个数num[i],输出符合给出的条件且字典序最小的从左到右队列里每个人的身高。

题解:人有100000个,可以从线段树方法考虑,把问题转化为把每个人前面能留多少个空位给高个子的人,可以先按身高从小到大排个序,考虑第i个人前面留的位置肯定是num[i]或n-i-num[i]中的较小值,这样才能让字典序最小,一旦有n - i - num[i]的值小于0说明无解。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100000 + 5;
struct Peo {
int h, num;
}p
;
int n, s[N << 2], res
;

bool cmp(Peo a, Peo b) {
return a.h < b.h;
}

void pushup(int k) {
s[k] = s[k * 2] + s[k * 2 + 1];
}

void build(int k, int left, int right) {
if (left == right) {
s[k] = 1;
return;
}
int mid = (left + right) / 2;
build(k * 2, left, mid);
build(k * 2 + 1, mid + 1, right);
pushup(k);
}

void modify(int k, int left, int right, int pos, int val) {
if (left == right) {
res[left] = val;
s[k] = 0;
return;
}
int mid = (left + right) / 2;
if (pos <= s[k * 2])
modify(k * 2, left, mid, pos, val);
else
modify(k * 2 + 1, mid + 1, right, pos - s[k * 2], val);
pushup(k);
}

int main() {
int t, cas = 1;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
build(1, 1, n);
for (int i = 1; i <= n; i++)
scanf("%d%d", &p[i].h, &p[i].num);
sort(p + 1, p + n + 1, cmp);
int flag = 0;
for (int i = 1; i <= n; i++) {
int m = n - i;
int temp = m - p[i].num;
if (temp < 0) {
flag = 1;
break;
}
if (p[i].num < temp)
modify(1, 1, n, p[i].num + 1, p[i].h);
else
modify(1, 1, n, temp + 1, p[i].h);
}
printf("Case #%d: ", cas++);
if (flag) {
printf("impossible\n");
continue;
}
printf("%d", res[1]);
for (int i = 2; i <= n; i++)
printf(" %d", res[i]);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: