POJ 2104/TYVJ 1253 划分树模板

求区间第k小值~

详细注释见代码:

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #define M 100005
 6 using namespace std;
 7 int sorted[M],toleft[30][M],tree[30][M],m,n;
 8 void read()
 9 {
10     for(int i=1;i<=m;i++)
11     {
12         scanf("%d",&sorted[i]);
13         tree[0][i]=sorted[i];
14     }
15     sort(sorted+1,sorted+1+m);
16 }
17 void create(int l,int r,int d)
18 {
19     if(l==r) return;
20     int mid=(l+r)>>1;
21     int same=mid-l+1;//左子树中的数字个数 
22     for(int i=l;i<=r;i++)
23         if(tree[d][i]<sorted[mid]) same--;//此时same成为和中位数相等的位于左子树的数字个数 
24         
25     int ls=l,rs=mid+1;//分别为左右区间的起点 
26     for(int i=l;i<=r;i++)
27     {
28         int fg=0;
29         if((tree[d][i]<sorted[mid])||(tree[d][i]==sorted[mid]&&same>0))//将符合条件的数分到左子树 
30         {
31             fg=1;
32             tree[d+1][ls++]=tree[d][i];
33             if(tree[d][i]==sorted[mid]) same--;//有些与中位数相同的数分到左子树,剩下的分到右子树 
34         }
35         else tree[d+1][rs++]=tree[d][i];//分到右子树 
36         toleft[d][i]=toleft[d][i-1]+fg;//toleft[d][i]表示从l到i区间中有多少数分到了其左子树中 
37     }
38     //递归建树 
39     create(l,mid,d+1);
40     create(mid+1,r,d+1);
41 }
42 int query(int ql,int qr,int k,int l,int r,int d)
43 {
44     if(ql==qr) return tree[d][ql];
45     int mid=(l+r)>>1;
46     int x=toleft[d][ql-1]-toleft[d][l-1];//位于ql(待求区间左端点)(不包括ql)左边的放于左子树中的数字个数 
47     int y=toleft[d][qr]-toleft[d][l-1];//位于qr(待求区间右端点)(包括qr)左边的放于左子树中的数字个数
48     int ry=qr-l+1-y;//位于qr(包含qr)的在右子树中的数字个数 
49     int cnt=y-x;//位于区间[ql,qr]中的在左子树中的数字个数 
50     int rx=ql-l-x;//位于ql左边(不包含ql)的在右子树中的数字个数 
51     if(cnt>=k) return query(l+x,l+y-1,k,l,mid,d+1);
52     else return query(mid+rx+1,mid+ry,k-cnt,mid+1,r,d+1);
53 }
54 void go()
55 {
56     create(1,m,0);
57     for(int i=1,a,b,k;i<=n;i++)
58     {
59         scanf("%d%d%d",&a,&b,&k);
60         int ans=query(a,b,k,1,m,0);
61         printf("%d\n",ans);
62     }
63 }
64 int main()
65 {
66     while(scanf("%d%d",&m,&n)!=EOF)
67     {
68         read();
69         go();
70     }
71     return 0;
72 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2713548.html