Description
N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood ‘watering hole’ and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands.
Regrettably, FJ does not have a way to sort them. Furthermore, he’s not very good at observing problems. Instead of writing down each cow’s brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow.
Given this data, tell FJ the exact ordering of the cows.
【题目分析】
简单的递推题目,加入树状数组优化之后只有nlogn的复杂度。
按理说用平衡树也是同样的复杂度,但是过不了。真是干(sang)的(xin)漂(bing)亮(kuang)。
【代码】
一、平衡树
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct node{
int l,r,v,w,size,rand;//v值 w次数
}t[10100];
int a[10001],b[10001];
int root,cnt=0,ans;
inline void up(int k)
{t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].w;}
inline void rturn(int &k)
{
int now=t[k].l;
t[k].l=t[now].r;
t[now].r=k;
t[now].size=t[k].size;
up(k);
k=now;
}
inline void lturn(int &k)
{
int now=t[k].r;
t[k].r=t[now].l;
t[now].l=k;
t[now].size=t[k].size;
up(k);
k=now;
}
inline void insert(int &k,int x)
{
if (k==0) {t[++cnt].v=x;t[cnt].w=1;t[cnt].size=1;t[cnt].rand=rand();k=cnt;return ;}
t[k].size++;
if (x==t[k].v) t[k].w++;
else if (x>t[k].v){insert(t[k].r,x);if (t[t[k].r].rand<t[k].rand);lturn(k);}
else {insert(t[k].l,x);if (t[t[k].l].rand<t[k].rand);rturn(k);}
}
inline void del(int &k,int x)
{
if (k==0) return ;
if (t[k].v==x)
{
if (t[k].w>1)
{
t[k].w--;
t[k].size--;
return ;
}
else{
if (t[k].l*t[k].r==0) k=t[k].l+t[k].r;
else if (t[t[k].l].rand<t[t[k].r].rand){
rturn(k);del(k,x);
}
else lturn(k),del(k,x);
}
return;
}
t[k].size--;
if (t[k].v<x) del(t[k].r,x);
else del(t[k].l,x);
}
inline int qn(int &k,int x)//询问数字
{
if (k==0) return 0;
if (x<=t[t[k].l].size) return qn(t[k].l,x);
if (x>t[t[k].l].size+t[k].w) return qn(t[k].r,x-t[t[k].l].size-t[k].w);
else return t[k].v;
}
int main()
{
int n;
scanf("%d",&n);
for (int i=2;i<=n;++i) scanf("%d",&a[i]);
for (int i=1;i<=n;++i) insert(root,i);
for (int i=n;i>=1;--i)
{
ans=qn(root,a[i]+1);
b[i]=ans;
del(root,ans);
}
for (int i=1;i<=n;++i) printf("%d ",b[i]);
printf("\n");
}
二、树状数组
#include <cstdio>
#include <cstring>
int a[10001],n,t[10001],b[10001];
int lowbit(int x){return x&(-x);}
inline void inc(int x)
{while (x<=n){t[x]++;x+=lowbit(x);}}
inline void dev(int x)
{while (x<=n){t[x]--;x+=lowbit(x);}}
inline int sum(int x)
{int ans=0;while (x>=1) {ans+=t[x];x-=lowbit(x);}return ans;}
int main()
{
scanf("%d",&n);
for (int i=2;i<=n;++i) scanf("%d",&a[i]);
for (int i=1;i<=n;++i) inc(i);
for (int i=n;i>=1;--i)
{
int k=a[i]+1;
int l=1,r=n;
while (l<r)
{
int mid=(l+r)/2+1;
if (sum(mid)<=k) l=mid;
else r=mid-1;
}
b[i]=l;dev(l+1);
}
for (int i=1;i<=n;++i) printf("%d\n",b[i]);
}