HDU 5493 Queue (树状数组+二分+构造思维)*

 

Online JudgeOnline ExerciseOnline TeachingOnline ContestsExercise Author
F.A.Q
Hand In Hand
Online Acmers
Forum | Discuss
Statistical Charts

Problem Archive
Realtime Judge Status
Authors Ranklist
 

     C/C++/Java Exams     
ACM Steps
Go to Job
Contest LiveCast
ICPC@China

Best Coder beta
VIP | STD Contests
Virtual Contests
    DIY | Web-DIY beta
Recent Contests

Author njtech2010160220
Mail Mail 0(0)
Control Panel Control Panel
Sign Out Sign Out

 

Queue

Time 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.
Every person has a unique height, and we denote the height of the i-th person as hi. The i-th person remembers that there were ki people who stand before him and are taller than him. Ideally, this is enough to determine the original order of the queue uniquely. However, as they were waiting for too long, some of them get dizzy and counted ki in a wrong direction. ki could be either the number of taller people before or after the i-th person.
Can you help them to determine the original order of the queue?

 

 

Input

The first line of input contains a number T indicating the number of test cases (T≤1000).
Each test case starts with a line containing an integer N indicating the number of people in the queue (1≤N≤100000). Each of the next N lines consists of two integers hi and ki as described above (1≤hi≤109,0≤kiN−1). Note that the order of the given hi and ki is randomly shuffled.
The sum of N over all test cases will not exceed 106

 

 

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 

 

 

Statistic | Submit | Discuss | Note

Home | TopHangzhou Dianzi University Online Judge 3.0
Copyright © 2005-2018 HDU ACM Team. All Rights Reserved.
Designer & Developer : Wang Rongtao LinLe GaoJie GanLu
Total 0.000000(s) query 6, Server time : 2018-07-29 21:51:32, Gzip enabled
Administration

 

#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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值