*点击

[USACO03Open] Lost Cows

题目

Description

有 NN 头奶牛,已知它们的编号为 1∼N1N 且各不相同,但不知道每头奶牛的具体编号。

现在这 NN 头奶牛站成一列,已知第 ii 头奶牛前面有 aiai 头牛编号小于它,求每头奶牛的编号。

Input

第 11 行,输入一个整数 NN

第 2...N2...N 行,每行输入一个整数 aiai,表示第 ii 头奶牛前面有 aiai 头奶牛的编号小于它(因为第一头奶牛前面没有奶牛,所以 ii 从 22 开始)。

Output

输出包含 NN 行,每行输出一个整数表示奶牛的编号。

第 ii 行输出第 ii 头奶牛的编号。

Sample Input

5
1
2
1
0

Sample Output

2
4
5
3
1

思路

面对从前往后处理无法确定答案;

这道题我们应该想到用倒序处理;

对于样例

$1$   $2$   $1$   $0$;

最后一个数前面比它小的数有$0$个;

所以最后一个数是$1$;

倒数第二个数前面比它小的数有$1$个;

就在剩下未确定的数$2$  $3$  $4$  $5$中寻找第二大的数;

倒数第三个数前面比它小的数有$2$个;

就在$2$  $4$  $5$中寻找第三大的数;

我们假设前面比它小的数个数为$b[i]$,那么这就是剩下未确定的数中的第$b[i]+1$大的数;

剩下的都是如此;

 

如果数据较大;

处理的方式可以选择线段树;

时间复杂度是$n\log2n$;

方法是把每个节点赋值为$1$;

把每个找到的数删除;

存下被删除的数就好了;

具体看代码~~;

 

代码

 

 1 #include<bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const ll _=1e5+1;
 5 ll n,tot;
 6 ll ans[_],b[_];
 7 struct tree
 8 {
 9     ll l,r,v,f;
10 }a[_];
11 void build(ll p,ll l,ll r)//建树
12 {
13     a[p].l=l; a[p].r=r;
14     if(l==r)
15     {
16         a[p].v=1;//赋值为1表示这个数未被确定且这个区间未被确定的数的个数
17         return;
18     }
19     ll mid=(l+r)>>1;
20     ll ls=p*2,rs=p*2+1;
21     build(ls,l,mid);
22     build(rs,mid+1,r);
23     a[p].v=a[ls].v+a[rs].v;
24 }
25 void findout(ll p,ll x)
26 {
27     if(a[p].l==a[p].r)
28     {
29         ans[++tot]=a[p].l;//找到第x大的数并储存
30         a[p].v=0;
31         return;
32     }
33     ll ls=p*2,rs=p*2+1;
34     if(x<=a[ls].v)//如果左子树中未被确定的数大于等于要寻找的第x个数
35         findout(ls,x);//说明要找的数在左子树
36     else
37         findout(rs,x-a[ls].v);//否则在右子树,且x要减去左子树中未被确定的数的个数
38     a[p].v=a[ls].v+a[rs].v;
39 }
40 int main()
41 {
42     scanf("%lld",&n);
43     for(ll i=2;i<=n;i++)//b[1]=0,第一个数前面比它小的数没有
44         scanf("%lld",&b[i]);
45     build(1,1,n);
46     for(ll i=n;i>=1;i--)
47         findout(1,b[i]+1);//前面比它小的数有b[i]个,那么这个数就是剩下未确定的数中的第b[i]+1个数
48     for(ll i=tot;i>=1;i--)
49         printf("%lld\n",ans[i]);
50     return 0;
51 }

 

posted @ 2024-11-23 21:29  木偶人-怪咖  阅读(3)  评论(0编辑  收藏  举报
*访客位置3D地图 *目录