HDU 5493 Queue (Binary + tree array)
N people are queuing up, and each person has a unique height, tell you how tall each person is and the number of people who are higher than him in front or back (it is unknown in the end ). You must restore the original queue with the smallest Lexicographic Order.
Thought: because the minimum Lexicographic Order is required, we can first sort by height from small to large. Suppose there are k people in front of or behind the person who is currently at the I level, then all the people in front of him are shorter than him, and n-I people are higher than him. If there are p vacancies in front of him, he is the person in the p + 1 vacancy, so how to calculate p? Because the minimum Lexicographic Order is required, p = min (k, n-I-k ). Why is this true? Each person has two possible positions. Because he is shorter than him, he can do whatever he is. To minimize the Lexicographic Order, select a smaller position. When n-I-k <0, there is no extra space, so there is no solution.
In order to speed up the algorithm, we use a tree array to determine the number of people in front of the person I to determine the number of free positions.
Complexity O (n * logn ).
For details, see the code:
#include
#include
#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define Max(a,b) ((a)>(b)?(a):(b))#define Min(a,b) ((a)<(b)?(a):(b))using namespace std;typedef long long ll;const double PI = acos(-1.0);const double eps = 1e-6;const int INF = 1000000000;const int maxn = 100000 + 5;int T,n,m,bit[maxn],kase=0,ans[maxn];struct node { int v, num; bool operator < (const node& rhs) const { return v < rhs.v; }}a[maxn];int sum(int x) { int ans = 0; while(x > 0) { ans += bit[x]; x -= x & -x; } return ans;}void add(int x, int d) { while(x <= n) { bit[x] += d; x += x & -x; }}int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); memset(bit, 0, sizeof(bit)); for(int i=1;i<=n;i++) { scanf("%d%d",&a[i].v,&a[i].num); } sort(a+1,a+n+1); bool ok = true; for(int i=1;i<=n;i++) { int k = min(a[i].num, n-i-a[i].num); int l = 1, r = n, mid; if(n - i - a[i].num < 0) { ok = false; break; } ++k; while(r > l) { mid = (r+l)/2; if(mid - sum(mid) >= k) r = mid; else l = mid + 1; } add(l, 1); ans[l] = a[i].v; } printf("Case #%d:",++kase); if(ok) { for(int i=1;i<=n;i++) { printf(" %d",ans[i]); } printf("\n"); } else printf(" impossible\n"); } return 0;}