基本思路就是,从后往前读取数字small[i]。在剩余编号集合里(一开始剩余编号集合为全集)查找第small[i]+1个编号,该编号就是对应位置牛的编号。
若直接用数组来做,则每次查找都需要遍历前n个数。而用线段树来做则可以降低为nlogn的复杂度。
事实上感觉可以直接用stl的set来做,直接模拟应该也能不超时得解。
本题主要用来熟悉线段树这个结构。
ac代码如下:
#include<iostream>
#include<cstdio>
#include<cstdio>
using namespace std;
const int maxn=;
int small[maxn],ans[maxn];
struct node{
int lc,rc,len;
};
node tree[maxn*];//这里一开始数组开小了出现了rte
void build(int x,int lc,int rc){
tree[x].lc=lc,tree[x].rc=rc;
tree[x].len=rc-lc+;
if(lc==rc)return ;
build(x*,lc,(lc+rc)/);
build(x*+,(lc+rc)/+,rc);
}
int query(int base,int k){
tree[base].len--;
if(tree[base].lc==tree[base].rc)return tree[base].lc;
if(k<=tree[base*].len){
return query(base*,k);
}
else{
return query(base*+,k-tree[base*].len);
}
}
int main(void){
int n;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&small[i]);
}
small[]=;
build(,,n);
for(int i=n;i>=;i--){
ans[i]=query(,small[i]+);
}
for(int i=;i<=n;i++){
printf("%d\n",ans[i]);
}
return ;
}