线段树模拟+贪心
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int oo = 1e9;
const double PI = acos(-1);
const int N = 1e6;
int n, Queue[N];
struct node
{
int high, more;
bool operator < (const node &a) const
{
return high < a.high;
}
} student[N];
struct da
{
int left, right, sum;
} as[N*4];
void build(int left ,int right , int i)
{
as[i].left = left;
as[i].right = right;
as[i].sum = right - left + 1;
int mid = (left + right) / 2;
if(left == right) return ;
build(left, mid, 2*i);
build(mid+1, right, 2*i+1);
}
void update(int i, int id)
{
if(as[i].left == as[i].right && as[i].left == id)
{
as[i].sum = 0;
return ;
}
if(id <= as[i*2].right) update(2*i, id);
else update(2*i+1, id);
as[i].sum = as[i*2].sum + as[i*2+1].sum;
}
int query(int i, int val, int sign)
{
if(val > as[i].sum) return oo;/**< 如果这个位置已经有人了 或者 这个人没有位置可站了 */
if(as[i].left == as[i].right) return as[i].left;
if(sign == 1)
{
if(val <= as[i*2].sum) return query(2*i, val, sign);
else return query(2*i+1, val - as[i*2].sum, sign);
}
if(sign == 0)
{
if(as[i*2+1].sum >= val) return query(2*i+1, val, sign);
else return query(2*i, val-as[i*2+1].sum, sign);
}
}
int main()
{
int T, i, cas = 1, ok;
scanf("%d", &T);
while(T--)
{
ok = 0;
memset(Queue, 0, sizeof(Queue));
scanf("%d", &n);
build(1, n, 1);
for(i = 0; i < n; i++)
scanf("%d %d", &student[i].high, &student[i].more);
sort(student, student + n);/**< 按照身高排序 */
for(i = 0; i < n; i++)
{
int l = query(1, student[i].more + 1, 1);/**< l,r 表示这个人可以插入的位置 */
int r = query(1, student[i].more + 1, 0);
int mini = min(l, r);/**< 找到最小的位置*/
if(mini == oo)
{
ok = 1;
break;
}
update(1, mini);
Queue[mini] = student[i].high;
}
if(ok)
{
printf("Case #%d: impossible\n", cas++);
continue;
}
printf("Case #%d:", cas++);
for(i = 1; i <= n; i++)
printf(" %d", Queue[i]);
printf("\n");
}
return 0;
}
原文:http://www.cnblogs.com/PersistFaith/p/4844136.html