HDU 5493 Queue 树状数组

时间:2023-03-09 00:52:46
HDU 5493 Queue 树状数组

Queue

Time Limit: 1 Sec

Memory Limit: 256 MB

题目连接

http://acm.hdu.edu.cn/showproblem.php?pid=5493

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≤ki≤N−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

HINT

题意

给你一些人,每个人的身高都是不一样的

然后再给你一个k,表示这个人的左边或者右边,有k个人比他高

然后让你构造一个序列,满足这个条件

题解:

每个人其实可以站两个位置,不是左边就是右边

你从小到大插入的话,那么剩下没插的位置都是比你大的

你就插进去就好

用树状数组/splay/treap维护一下就好了

HDU 5493 Queue 树状数组

代码:

//qscqesze
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <bitset>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200006
#define mod 1000000007
#define eps 1e-9
#define e exp(1.0)
#define PI acos(-1)
#define lowbit(x) (x)&(-x)
const double EP = 1E- ;
int Num;
//const int inf=0x7fffffff;
const ll inf=;
inline ll read()
{
ll x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
//*************************************************************************************
int n,val1[maxn],val2[maxn]; void add(int * vc,int u ,int v)
{
while(u <= n )
{
vc[u] += v;
u += lowbit(u);
}
} int query(int * vc,int u)
{
int res=;
while(u)
{
res += vc[u];
u -= lowbit(u);
}
return res;
} int RankGet(int * vc,int k)
{
int L = , R = n;
while(L < R)
{
int mid = L + ((R-L)>>);
int res = query(vc,mid);
//cout << "mid is " << mid << " res is " << res << endl;
if(res == k) R = mid;
else if(res < k) L = mid + ;
else R = mid - ;
}
return L;
} struct kkk
{
int x,y;
};
bool cmp(kkk aa,kkk bb)
{
return aa.x<bb.x;
}
kkk p[maxn];
int ans[maxn];
vector<int> v1,v2;
int main()
{
// freopen("in.txt","r",stdin);
int t=read();
for(int cas=;cas<=t;cas++)
{
n=read();
for(int i=;i<=n;i++)
{
p[i].x=read(),p[i].y=read();
p[i].y++;
}
sort(p+,p+n+,cmp);
int flag=;
memset(val1,,*(n+));memset(val2,,*(n+));
for(int i = ; i <= n ; ++ i)
{
add(val1,i,);
add(val2,i,);
}
//return 0;
for(int i=;i<=n;i++)
{
if(p[i].y>n-i+)
{
flag=;
break;
}
int p1 = RankGet(val1,p[i].y);
int p2 = n-RankGet(val2,p[i].y) + ;
// cout << "i is " << i << " p1 is " << p1 << " p2 is " << p2 << endl;
// int p1=v1[p[i].y],p2=v2[p[i].y];
if(p1<p2)
{
ans[p1]=p[i].x;
add(val1,p1,-);
add(val2,n-p1+,-);
//cout << "up delete " << p1 << " down delete " << n-p1 +1 << endl;
//v1.erase(v1.begin()+p[i].y);
//v2.erase(v2.begin()+n-i+2-p[i].y);
}
else
{
ans[p2]=p[i].x;
add(val1,p2,-);
add(val2,n-p2+,-);
// cout << "up delete " << p2 << " down delete " << n-p2 +1 << endl;
//v2.erase(v2.begin()+p[i].y);
//v1.erase(v1.begin()+n-i+2-p[i].y);
}
// cout << endl;
}
printf("Case #%d:",cas);
if(!flag)
{
printf(" impossible\n");
}
else
{
for(int i=;i<=n;i++)
printf(" %d",ans[i]);
printf("\n");
}
}
}