首页 > 代码库 > 名校联赛第三天A层 问题 B: Number

名校联赛第三天A层 问题 B: Number

问题 B: Number

时间限制: 1 Sec  内存限制: 256 MB

题目描述

一个排列,求出了 a 数组,其中 ai 表示第 i 个数左边有多少个数比它小

计算出原来的排列

输入

第一行输入 n 接下来 n - 1 个整数 ai,下标从 2 开始

输出

输出 n 个整数表示原排列

样例输入

5
1
2
1
0

样例输出

2
4
5
3
1

提示

 


对于 20% 的数据满足:1 ≤ n ≤ 10



对于 50% 的数据满足:1 ≤ n ≤ 1000



对于 100% 的数据满足,1 ≤ n ≤ 100000



保证解存在

  这道题说来蛮可惜的,当时正解的原理都已经想明白了,然而,然而居然因为第一题太烦心,没仔细去向正解,只想着拿暴力分,呵呵了。

  不知道大家想没想出来,数列中最小的数是最右方的0,次小数就是将0右方的所有数-1后 最右方的0,以此类推……所以就很好想了,题目数据可以让我们去确定n logn,因为在枚举每一位数时已经有n的复杂度了,因此我们需要一个为log n复杂度的东西求出来区间最小,线段树就好了,当然,平衡树也可以,只不过是熟悉线段树才打的线段树罢了。

技术分享
  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<map>
  7 #include<queue>
  8 #include<string>
  9 #include<cmath>
 10 using namespace std;
 11 int n,m,a[100005];
 12 struct no{
 13     int left,right;
 14     int mid;
 15     int mn,lazy;
 16 }node[500005];
 17 void build(int left,int right,int x){
 18     node[x].left=left;
 19     node[x].right=right;
 20     if(left==right)
 21     {
 22         node[x].mn=a[left];
 23         return;
 24     }
 25     int mid=(left+right)/2;
 26     node[x].mid=mid;
 27     build(left,mid,2*x);
 28     build(mid+1,right,2*x+1);
 29     node[x].mn=min(node[x*2].mn,node[2*x+1].mn);
 30 }
 31 void pushdown(int x){
 32     if(node[x].lazy)
 33     {
 34         node[2*x].lazy+=node[x].lazy;
 35         node[2*x+1].lazy+=node[x].lazy;
 36         node[x*2].mn+=node[x].lazy;
 37         node[2*x+1].mn+=node[x].lazy;
 38         node[x].lazy=0;
 39     }
 40 }
 41 void add(int left,int right,int x,int z){
 42     if(node[x].left==left&&node[x].right==right)
 43     {
 44         node[x].mn+=z;
 45         node[x].lazy+=z;
 46         return;
 47     }
 48     pushdown(x);
 49     int mid=node[x].mid;
 50     if(right<=mid)
 51         add(left,right,2*x,z);
 52     else if(mid<left)
 53         add(left,right,2*x+1,z);
 54     else
 55     {
 56         add(left,mid,2*x,z);
 57         add(mid+1,right,2*x+1,z);
 58     }
 59     node[x].mn=min(node[x*2].mn,node[x*2+1].mn);
 60 }
 61 void change(int left,int right,int x,int z){
 62     if(node[x].left==node[x].right)
 63     {
 64         node[x].mn=z;
 65         return;
 66     }
 67     pushdown(x);
 68     int mid=node[x].mid;
 69     if(left<=mid)
 70         change(left,right,x*2,z);
 71     else
 72         change(left,right,2*x+1,z);
 73     node[x].mn=min(node[2*x].mn,node[2*x+1].mn);
 74     return;
 75 }
 76 int get(int x){
 77     if(node[x].left==node[x].right)
 78     {
 79         return node[x].left;
 80     }
 81     pushdown(x);
 82     if(node[2*x+1].mn==0)
 83         return get(2*x+1);
 84     else
 85         return get(2*x);
 86 }
 87 int b[100005];
 88 int main(){
 89     scanf("%d",&n);
 90     for(int i=2;i<=n;i++)
 91         scanf("%d",&a[i]);
 92     build(1,n,1);
 93     for(int i=1;i<=n;i++)
 94     {
 95         int x=get(1);
 96         b[x]=i;
 97         change(x,x,1,0x7fffffff);
 98         if(x<n)
 99             add(x+1,n,1,-1);
100     }
101     for(int i=1;i<=n;i++)
102         printf("%d\n",b[i]);
103     //while(1);
104     return 0;
105 }
View Code

 

名校联赛第三天A层 问题 B: Number