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 }

 

你可能感兴趣的:(poj)