poj2182_线段树
题意:有一个1到n的一个被打乱的排列,告诉你每个数的左边有多少个数比它小,显然第一个数左边没有比它小的数,求每个位置上的数。
分析:用树状数组可以求出某一个序列中所有左边小于等于array[]的个数。这个题正好相反,已知每个数左边小于它的个数,求这个序列。用树状数组也可以做,但是没有线段树好理解。
线段树中num记录[l,r]中还剩余多少人尚未被确定
代码:
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <memory.h> 4 using namespace std; 5 const int maxnum=8001; 6 struct node 7 { 8 int l,r; 9 int num; //num记录[l,r]中还剩余多少人尚未被确定 10 }tree[maxnum*4]; 11 int array[maxnum]; 12 int res[maxnum]; 13 int n; 14 15 void build_tree(int cur,int l,int r) 16 { 17 tree[cur].l=l; 18 tree[cur].r=r; 19 tree[cur].num=r-l+1; 20 if(l==r) return ; 21 int m=(l+r)/2; 22 build_tree(2*cur+1,l,m); 23 build_tree(2*cur+2,m+1,r); 24 } 25 26 int query(int cur,int num) 27 { 28 tree[cur].num--; 29 if(tree[cur].l==tree[cur].r) 30 return tree[cur].l; 31 if(tree[2*cur+1].num>=num) 32 return query(2*cur+1,num); 33 else 34 { 35 num=num-tree[2*cur+1].num; 36 return query(2*cur+2,num); 37 } 38 } 39 40 int main() 41 { 42 int i; 43 scanf("%d",&n); 44 build_tree(0,1,n); 45 46 array[1]=1; //小于等于 47 for(i=2;i<=n;i++) 48 { 49 scanf("%d",&array[i]); 50 array[i]+=1; 51 } 52 for(i=n;i>=1;i--) //从后往前 53 res[i]=query(0,array[i]); //从根开始找第array[i]位的数字 54 55 for(i=1;i<=n;i++) 56 printf("%d\n",res[i]); 57 return 0; 58 } 59 60 /* 61 5 62 0 63 2 64 0 65 4 66 */