poj2104_划分树

在算法篇介绍过求这样的某一个范围内第k大的数的三种方法。

分治方法,对于求一组范围内的值可以考虑。但是求多组的时候就不行了,因为这种方法会改变原数组的排序。如果要有多组询问时,就必须赋值到另外一个数组中,结果TLE.

代码:

View Code
 1 #include <iostream>

 2 #include <stdio.h>

 3 #include <memory.h>

 4 #include <algorithm>

 5 using namespace std;

 6 

 7 const int maxnum=100005;

 8 int array[maxnum];

 9 int a[maxnum];

10 

11 int patition(int p,int r)

12 {

13     int temp=a[r];

14     int i=p-1;

15     int j,t;

16     for(j=p;j<=r-1;j++)

17     {

18         if(a[j]<=temp)

19         {

20             i++;

21             t=a[i];

22             a[i]=a[j];

23             a[j]=t;

24         }

25     }

26     t=a[i+1];

27     a[i+1]=a[r];

28     a[r]=t;

29     return i+1;

30 }

31 

32 int select(int p,int r,int i)

33 {

34     if(p==r)

35         return a[p];

36     int q=patition(p,r);

37     int k=q-p+1;

38     if(k==i)

39         return a[q];

40     else if(i<k)

41         return select(p,q-1,i);

42     else

43         return select(q+1,r,i-k);

44 }

45 

46 void function(int p,int r,int i)

47 {

48     int k;

49     int cnt=0;

50     for(k=p;k<=r;k++)

51         a[cnt++]=array[k];

52 //    for(k=0;k<cnt;k++)

53 //        cout<<a[k]<<" ";

54 //    cout<<endl;

55     printf("%d\n",select(0,cnt-1,i));

56 }

57 

58 int main()

59 {

60     int n,m;

61     scanf("%d%d",&n,&m);

62     int i,p,q,j;

63     for(i=0;i<n;i++)

64         scanf("%d",&array[i]);

65     while(m--)

66     {

67         scanf("%d%d%d",&p,&q,&j);

68         function(p-1,q-1,j);

69     }

70     return 0;

71 }

72 

73 

74 /*

75 6 1

76 1 1 1 1 1 1

77 3 5 2

78 */

 

划分树方法可以用于求多组的情况,且查询时间复杂度O(lgn)

代码:

View Code
  1 #include <iostream>

  2 #include <stdio.h>

  3 #include <algorithm>

  4 #include <memory.h>

  5 using namespace std;

  6 const int maxnum=100005;

  7 struct node

  8 {

  9     int array[maxnum];

 10     int sum[maxnum];

 11 }tree[20];   //树有10层

 12 int sorted[maxnum];

 13 

 14 void Build_tree(int cur,int l,int r)

 15 {

 16     if(l==r)

 17         return ;

 18     int m=(l+r)/2;

 19     int i;

 20 

 21     int lsame=m-l+1; //这是往cur+1左子树中一共放入的节点,其中小于中值的一定在左子树中,等于中值的可能在左子树,也可能在右子树

 22     for(i=l;i<=r;i++)

 23         if(tree[cur].array[i]<sorted[m])

 24             lsame--;//与中值相同的放在左子树中的个数

 25 

 26     int lnum=l,rnum=m+1;

 27     for(i=l;i<=r;i++)

 28     {

 29         if(i==l)

 30             tree[cur].sum[i]=0;

 31         else

 32             tree[cur].sum[i]=tree[cur].sum[i-1];

 33         if(tree[cur].array[i]<sorted[m])

 34         {

 35             tree[cur].sum[i]++;

 36             tree[cur+1].array[lnum++]=tree[cur].array[i];

 37         }

 38         else if(tree[cur].array[i]>sorted[m])

 39             tree[cur+1].array[rnum++]=tree[cur].array[i];

 40         else   //if(tree[cur].array[i]==sorted[m])

 41         {

 42             if(lsame>0)

 43             {

 44                 lsame--;

 45                 tree[cur].sum[i]++;

 46                 tree[cur+1].array[lnum++]=tree[cur].array[i];

 47             }

 48             else

 49                 tree[cur+1].array[rnum++]=tree[cur].array[i];

 50         }

 51     }

 52     Build_tree(cur+1,l,m);

 53     Build_tree(cur+1,m+1,r);

 54 }

 55 

 56 int find(int cur,int st,int ed,int l,int r,int k)

 57 {

 58     //cout<<cur<<" "<<st<<" "<<ed<<" "<<l<<" "<<r<<" "<<k<<endl;

 59     if(l==r)

 60         return tree[cur].array[l];

 61     int m=(st+ed)/2;

 62     int lnum,rnum;

 63     if(l-1<st)

 64         lnum=0;

 65     else

 66         lnum=tree[cur].sum[l-1];

 67     rnum=tree[cur].sum[r];

 68     if(rnum-lnum>=k)//表示有几个点进入左子树

 69         return find(cur+1,st,m,st+lnum,st+rnum-1,k);

 70     else

 71         return find(cur+1,m+1,ed,m+1+(l-st-lnum),m+1+(r-st-rnum),k-(rnum-lnum));

 72 }

 73 

 74 

 75 int main()

 76 {

 77     int n,m;

 78     scanf("%d%d",&n,&m);

 79     int i;

 80     for(i=1;i<=n;i++)

 81     {

 82         scanf("%d",&tree[0].array[i]);

 83         sorted[i]=tree[0].array[i];

 84     }

 85     sort(sorted+1,sorted+n+1);

 86     Build_tree(0,1,n);

 87 

 88     int p,r,k;

 89     int res;

 90     while(m--)

 91     {

 92         scanf("%d%d%d",&p,&r,&k);

 93         res=find(0,1,n,p,r,k);

 94         printf("%d\n",res);

 95     }

 96 

 97     return 0;

 98 }

 99 

100 

101 /*

102 6 1

103 1 1 1 1 1 1

104 2 4 2

105 10 7 2 5 1 4 6

106 */

107 

108 

109 //    for(i=0;i<4;i++)

110 //    {

111 //        cout<<i<<endl;

112 //        for(j=1;j<maxnum;j++)

113 //            cout<<tree[i].array[j]<<" ";

114 //        cout<<endl;

115 //        for(j=1;j<maxnum;j++)

116 //            cout<<tree[i].sum[j]<<" ";

117 //        cout<<endl;

118 //    }


tju oj2722

你可能感兴趣的:(poj)