![]() | ||||||||||
| ||||||||||
QueueTime Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1466 Accepted Submission(s): 752 Problem Description N people numbered from 1 to N are waiting in a bank for service. They all stand in a queue, but the queue never moves. It is lunch time now, so they decide to go out and have lunch first. When they get back, they don’t remember the exact order of the queue. Fortunately, there are some clues that may help.
Input The first line of input contains a number T indicating the number of test cases (T≤1000).
Output For each test case, output a single line consisting of “Case #X: S”. X is the test case number starting from 1. S is people’s heights in the restored queue, separated by spaces. The solution may not be unique, so you only need to output the smallest one in lexicographical order. If it is impossible to restore the queue, you should output “impossible” instead.
Sample Input 3 3 10 1 20 1 30 0 3 10 0 20 1 30 0 3 10 0 20 0 30 1
Sample Output Case #1: 20 10 30 Case #2: 10 20 30 Case #3: impossible
Source 2015 ACM/ICPC Asia Regional Hefei Online
Recommend wange2014 | We have carefully selected several similar problems for you: 6318 6317 6316 6315 6314
| ||||||||||
|
#include<iostream>
#include<algorithm>
#include<string>
#include<map>//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include<set>//int gcd(int a,int b){return b?gcd(b,a%b):a;}
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define mod 1e9+7
#define ll long long
#define maxn 100005
#define MAX 1000000000
#define ms memset
using namespace std;
int tree[maxn];///存储树状数组前缀和
int ans[maxn];
int n;
/*
题目大意:一个高度序列被打乱,
每个高度都有对应的k值,
代表从前往后或者从后往前有k个数比其大。
问是否存在字典序最小的符合要求的序列,并输出,
如果不存在则输出impossible。
树状数组应用其中,
首先每个位置初始权重为1,
表示符合条件的位置。
先按身高从小到大排序,
然后指定pos的大小,即前面(或后面)要有多少人,
把这个指标带到树状数组里去二分取下界。
如果不存在则直接判定失败,存在的话则更新位置数据。
*/
int lowbit(int x) { return x & (-x) ; }
int sum(int x)
{
int res=0;
for(;x>0;res+=tree[x],x-=lowbit(x));
return res;
}
void add(int x,int d) { for( ; x<=n ; tree[x]+=d , x+=lowbit(x) ) ; }
/*
int h[maxn],k[maxn];
*/
struct node
{
int h,k;
node(){}
};
node line[maxn];
bool cmp(node x,node y)
{
return x.h<y.h;
}
int main()
{
int t;scanf("%d",&t);
for(int ca=1;ca<=t;ca++)
{
memset(tree,0,sizeof(tree));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&line[i].h,&line[i].k) ;
add(i,1);
}
sort(line+1,line+n+1,cmp);///从小到大插入如果存在符合题意的肯定能构造出序列。
int flag=1;
for(int i=1;i<=n;i++)
{
int pos=min(line[i].k+1 , n-i-line[i].k+1);///保证字典序最小
if(pos<1) flag=0;
if(flag==0) break;
int l=1,r=n;
int output=-1;
while(r>=l)
{
int mid=(l+r)>>1;
if(sum(mid)<pos) l=mid+1;
else
{
output=mid;
r=mid-1;
}
}
if(output==-1) flag=0;
else
{
ans[output]=line[i].h;
add(output,-1);///以后的因为有这个数的存在而减少了1,影响因子
}
}
printf("Case #%d: ",ca);
if(flag==0) puts("impossible");
else
{
for(int i=1;i<=n;i++)
{
if(i==1) printf("%d",ans[i]);
else printf(" %d",ans[i]);
}
puts("");
}
}
return 0;
}