名校联赛第三天A层 问题 B: Number
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了名校联赛第三天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 }
以上是关于名校联赛第三天A层 问题 B: Number的主要内容,如果未能解决你的问题,请参考以下文章