划分树 POJ2104
划分树
理解:建树的时候,bulid(int f,int e,int root,int d),在区间[f,e]中,将线段树左右端点(root的左右值)设为f和e。当前层是第d层,将下一层的左右子树分类好,即算出这一层在[f,e]区间的中值data[mid],之后小于data[mid]的值放d+1层的左边,大于data[mid]的值放d+1层的右边。建完树之后会打表将建树的过程在每一层记录下来。最多建20层,因为2^20已经足够存储很大的数列了。
update的时候通过递归,确定在下一层左右哪一个子树,递归到下一层的时候减小所求区间,直到区间长度为1时,返回区间值。
1 #include <iostream> 2 #include <string> 3 #include <algorithm> 4 #define MAX 100010 5 #define DEPTH 20 6 using namespace std; 7 int lessMid[DEPTH][MAX]; 8 int seg[DEPTH][MAX]; 9 int data[MAX]; 10 int n; 11 struct seg_tree 12 { 13 int l,r; 14 }tr[MAX*4]; 15 void bulid(int f,int e,int root,int d) 16 { 17 tr[root].l=f; 18 tr[root].r=e; 19 if(f==e) return; 20 int mid=(f+e)>>1; 21 int lsame=mid-f+1; 22 for(int i=f;i<=e;i++){ 23 if(seg[d][i]<data[mid]) 24 lsame--; //得出实际能放几个相同的数 25 } 26 int lson=f,rson=mid+1,same=0; 27 for(int i=f;i<=e;i++){ 28 if(i==f) 29 lessMid[d][i]=0; //表示在[f,e]内有几个数小于等于DATA[MID] 30 else lessMid[d][i]=lessMid[d][i-1]; 31 if(seg[d][i]<data[mid]){ 32 lessMid[d][i]++; 33 seg[d+1][lson++]=seg[d][i]; 34 }else if(seg[d][i]>data[mid]) 35 seg[d+1][rson++]=seg[d][i]; 36 else{ 37 if(same<lsame){ 38 same++; 39 lessMid[d][i]++; 40 seg[d+1][lson++]=seg[d][i]; 41 }else seg[d+1][rson++]=seg[d][i]; 42 } 43 } 44 bulid(f,mid,root*2,d+1); 45 bulid(mid+1,e,root*2+1,d+1); 46 } 47 int update(int f,int e,int root,int d,int cnt) 48 { 49 if(f==e) return seg[d][f]; 50 int s; 51 int ss; 52 if(f==tr[root].l) 53 { 54 s=lessMid[d][e]; 55 ss=0; 56 }else { 57 s=lessMid[d][e]-lessMid[d][f-1]; //表示在[f,e]内有几个小于等于data[MID]的个数 58 ss=lessMid[d][f-1]; //表示在[tr[root].l,f-1]内有几个小于等于data[MID]的个数 59 } 60 if(s>=cnt){ 61 return update(tr[root].l+ss,tr[root].l+ss+s-1,root*2,d+1,cnt); //区间长度减小1,d+1层的右端点是tr[root].l+ss+s-1
62 }else{ 63 int mid=(tr[root].l+tr[root].r)>>1; 64 int bb=f-tr[root].l-ss; 65 int b=e-f-s+1; 66 return update(mid+bb+1,mid+bb+b,root*2+1,d+1,cnt-s); //区间长度减小1,d+1层的左端点是mid+bb+1
67 } 68 } 69 int main() 70 { 71 int m; 72 while(scanf("%d%d",&n,&m)!=EOF){ 73 for(int i=1;i<=n;i++){ 74 scanf("%d",&seg[1][i]); 75 data[i]=seg[1][i]; 76 } 77 sort(data+1,data+1+n); 78 bulid(1,n,1,1); 79 int l,r,cnt; 80 for(int i=0;i<m;i++){ 81 scanf("%d%d%d",&l,&r,&cnt); 82 printf("%d\n",update(l,r,1,1,cnt)); 83 } 84 } 85 return 0; 86 }