您的位置:首页 > 理论基础 > 计算机网络

HDU 5493 Queue (线段树) 2015合肥网络赛

2015-09-28 16:40 573 查看
题意:

给定N<105个人的序列,N个(height,k)二元组描述这个序列

height:=这个人的身高,k:=这个人的左边或者右边有k个人比他高

构造一个字典序最小的序列满足这些条件

分析:

从高到低放或者从低到高放都可以,由于本题要输出字典序最小的序列,所以我们使用从低到高放

由于从低到高放,之后放进去的是都是比当前高的

考虑当前当前放进去的第i个人,要满足后来的(即比他高的)有恰好k个在他前面或者在他后面

考虑有后来的k个人在他前面就是前面预留出k个位置

考虑有后来的k个人在他后面,已经放了i−1个人,剩下有n−(i−1)个人,再放k个在后面,还有n−(i−1)−k个,再去掉自己

那么问题就转化成了前面预留n−(i−1)−k−1=>n−i−k个

由于要字典序最小的,小的尽量往前放,所以取个min(k,n−i−k),如果这个值为负了,那么就表示不能放,就是impossible了

接下来就是普通的线段树求第min(k,n−i−k)+1个位置放进去当前这个人,维护区间坑位的个数,查询的时候同时维护一下ans数组就好了

代码:

//
//  Created by TaoSama on 2015-09-28
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e5 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

int n, ans
;
int sum[N << 2];
typedef pair<int, int> P;
P a
;

#define root 1, n, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

void build(int l, int r, int rt) {
sum[rt] = r - l + 1;
if(l == r) return;
int m = l + r >> 1;
build(lson);
build(rson);
}

void update(int k, int v, int l, int r, int rt) {
--sum[rt];
if(l == r) {
ans[l] = v;
return;
}
int m = l + r >> 1;
if(sum[rt << 1] > k) update(k, v, lson);
else update(k - sum[rt << 1], v, rson);
}

int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
ios_base::sync_with_stdio(0);

int t; scanf("%d", &t);
int kase = 0;
while(t--) {
scanf("%d", &n);
for(int i = 1; i <= n; ++i) scanf("%d%d", &a[i].first, &a[i].second);
sort(a + 1, a + 1 + n);
build(root);
bool ok = true;
for(int i = 1; i <= n; ++i) {
int k = a[i].second, v = a[i].first;
k = min(k, n - i - k);
if(k < 0) {
ok = false;
break;
}
update(k, v, root);
}
printf("Case #%d: ", ++kase);
if(!ok) puts("impossible");
else for(int i = 1; i <= n; ++i) printf("%d%c", ans[i], " \n"[i == n]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息