题意:题意:FJ有n头牛,编号为1~n,它们并没有按照编号的顺序排好队。现在,FJ只知道每一个牛前面有多少只牛的编号比它大。问你能不能判断出所有牛的编号。
思路:采用线段树。。假设一个编号高度为a[i],那么它的编号肯定是a[i]+1,所以我们倒着想,先求出最后一只牛的编号,然后去掉,这时剩下n-1只牛,又可以从n-1里找高度为a[i-1]的牛,所以有a[i]+1=nk-k,k代表被去掉的牛数,nk其实就是剩下的牛数
代码:(转)
#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <map>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#define LL long long
using namespace std;
const int M=8005;
int a[M],ans[M];
int n;
struct Node
{
int l,r,len;
} node[3*M];
void build(int left,int right,int num)
{
node[num].l=left;
node[num].r=right;
node[num].len=right-left+1;
if(left==right)return;
build(left,(left+right)/2 , 2*num);
build((left+right)/2 + 1,right,2*num+1);
}
int query(int num,int l)
{
node[num].len--;// 查询+维护,关键一点:所求值为当前区间的左起第L个元素。
if(node[num].l==node[num].r)// 对访问到的区间维护len。
return node[num].l;
// 情况1:左子区间的数字个数不够,则查询右子区间的左起第num - node[u<<1].len个元素。
if(node[2*num].len<l)
{
return query(2*num+1,l-node[2*num].len);
}
// 情况2:左子区间的数字个数足够,则依旧查询左子区间的左起第num个元素
if(node[2*num].len>=l)
return query(2*num,l);
}
int main()
{
scanf("%d",&n);
a[1]=0;
for(int i=2; i<=n; i++)
{
scanf("%d",&a[i]);
}
build(1,n,1);
for(int i=n; i>=1; i--)
{
ans[i]=query(1,a[i]+1);
}
for(int i=1; i<=n; i++)
printf("%d\n",ans[i]);
return 0;
}