题目链接如下:
假设输入的所有排名是pre[i],其中pre[0]=0,那么我们每次倒过来取第pre[i]+1个数字就可以了。
目录
1.暴力解决
就和分析的一样,我们每次只要选出剩下的数组里边特定位置的数字就可以了。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<string>
using namespace std;
#define MAXN 20001
int n;
int pre[MAXN], ans[MAXN];
int num[MAXN];
int main(){
scanf("%d",&n);
pre[1]=0;
for (int i = 2; i <= n; ++i) {
scanf("%d",&pre[i]);
}
for (int i = 1; i <= n; ++i) {
num[i]=i;
}
int k;
for (int i = n; i > 0; --i) {
k=0;
for (int j = 1; j <= n; ++j) {
if (num[j]!=-1){
++k;
if (k==pre[i]+1){
ans[i]=j;
num[j]=-1;
break;
}
}
}
}
for (int i = 1; i <= n; ++i) {
printf("%d\n",ans[i]);
}
return 0;
}
2.普通二叉树实现线段树
用一颗树来维护区间,每个叶子节点代表的是某个数,那么我们相当于每次查找都维护这颗树就行了,并且还只要维护区间中点的个数就可以。
代码如下所示:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<string>
using namespace std;
#define MAXN 20001
struct {
int l,r,len;
}tree[MAXN];
int n;
int pre[MAXN], ans[MAXN];
void build_tree(int l,int r,int rt){
tree[rt].l=l;
tree[rt].r=r;
tree[rt].len=r-l+1;
if (l<r){
build_tree(l,(l+r)/2,rt<<1);
build_tree((l+r)/2+1,r,rt<<1|1);
}
}
int query(int num,int rt){
tree[rt].len--;
if (tree[rt].l==tree[rt].r){
return tree[rt].l;
}
if (tree[rt<<1].len>=num){
return query(num,rt<<1);
} else{
return query(num-tree[rt<<1].len,rt<<1|1);
}
}
int main(){
scanf("%d",&n);
build_tree(1,n,1);
pre[1]=0;
for (int i = 2; i <= n; ++i) {
scanf("%d",&pre[i]);
// cout<<pre[i]<<endl;
}
for (int i = n; i >= 1; --i) {
ans[i]=query(pre[i]+1,1);
}
for (int i = 1; i <= n; ++i) {
printf("%d\n",ans[i]);
}
return 0;
}
3.完全二叉树实现线段树
这里用tree记录区间内剩下数字的数量,建立一颗完全二叉树。
代码如下所示:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<vector>
#include<algorithm>
#include<cstring>
#include<set>
#include<map>
#include<queue>
#include<string>
#include<cmath>
using namespace std;
#define MAXN 20001
int n;
int pre[MAXN], ans[MAXN];
int tree[4*MAXN];
void build_tree(int last_left,int n){
for (int i = last_left; i < last_left+n; ++i) {
tree[i]=1;
}
while (last_left!=1){
for (int i = last_left/2; i < last_left; ++i) {
tree[i]=tree[i<<1]+tree[i<<1|1];
}
last_left/=2;
}
}
int query(int num,int rt,int last_left){
tree[rt]--;
if (tree[rt]==0 && rt>=last_left){
return rt;
}
if (tree[rt<<1]>=num){
return query(num,rt<<1,last_left);
} else{
return query(num-tree[rt<<1],rt<<1|1,last_left);
}
}
int main(){
scanf("%d",&n);
int last_left=1<<((int)(log((double)n)/ log(2.0))+1);
build_tree(last_left,n);
pre[1]=0;
for (int i = 2; i <= n; ++i) {
scanf("%d",&pre[i]);
}
for (int i = n; i > 0; --i) {
ans[i]=query(pre[i]+1,1,last_left)-last_left+1;
}
for (int i = 1; i <= n; ++i) {
printf("%d\n",ans[i]);
}
return 0;
}