查看文章
 
POJ 2104 归并树
2010-01-02 20:29
学到一个很强的数据结构,其实就是线段树+归并排序,把归并排序的每个阶段保存下来,然后就可以像线段树那样查询了。
可以快速查询一个序列中某一段x是第几大的、某一段第k大的数
因为每条线段都是有序的,所以可以二分查找一个数在这条线段上的rank值,利用线段树把查询的线段分成几个子线段,那么总的rank值就是这些子线段rank值的和。查询第k大的数再二分答案一下,一共3次二分(算上线段树),查询一次的时间为O(log(n)^3)

poj2104:

 1 #include<cstdio>
 2
 3 #define N 100000
 4 int n,max=-0x7fffffff,min=0x7fffffff;
 5 int a[N],tree[18][N];
 6 struct Node
 7 {
 8         int depth,left,right;
 9 }node[1<<19];
10
11 void MergeSort(int p,int depth,int l,int r)
12 {
13         node[p].depth=depth; node[p].left=l; node[p].right=r;
14         if(l+1==r) tree[depth][l]=a[l];
15         else
16         {
17                 int mid=(l+r)>>1;
18                 MergeSort(p<<1,depth+1,l,mid);
19                 MergeSort((p<<1)+1,depth+1,mid,r);
20                 int p1=l,p2=mid;
21                 while(l<r)
22                 {
23                         if(p1==mid)
24                                 tree[depth][l++]=tree[depth+1][p2++];
25                         else if(p2==r)
26                                 tree[depth][l++]=tree[depth+1][p1++];
27                         else
28                         {
29                                 if(tree[depth+1][p1]<tree[depth+1][p2])
30                                         tree[depth][l++]=tree[depth+1][p1++];
31                                 else
32                                         tree[depth][l++]=tree[depth+1][p2++];
33                         }
34                 }
35         }
36 }
37
38 void init()
39 {
40         for(int i=0;i<n;i++)
41         {
42                 scanf("%d",&a[i]);
43                 if(a[i]>max) max=a[i];
44                 if(a[i]<min) min=a[i];
45         }
46         MergeSort(1,0,0,n);
47 }
48
49 int Rank(int p,int l,int r,int x)
50 {
51         if(r<node[p].left || l>node[p].right) return 0;
52         if(l<node[p].left) l=node[p].left;
53         if(r>node[p].right) r=node[p].right;
54         if(l==node[p].left && r==node[p].right)
55         {
56                 r--;
57                 int depth=node[p].depth;
58                 if(x<=tree[depth][l]) return 0;
59                 if(x>tree[depth][r]) return r-l+1;
60                 while(l+1<r)
61                 {
62                         int mid=(l+r)>>1;
63                         if(tree[depth][mid]<x) l=mid;
64                         else r=mid;
65                 }
66                 return l-node[p].left+1;
67         }
68         return Rank(p<<1,l,r,x)+Rank((p<<1)+1,l,r,x);
69 }
70
71 int Query(int i,int j,int k)
72 {
73         int l=min,r=max+1;
74         while(l+1<r)
75         {
76                 int mid=(l+r)>>1;
77                 if(Rank(1,i,j,mid)+1>k) r=mid;
78                 else l=mid;
79         }
80         return l;
81 }
82
83 int main()
84 {
85         int q,i,j,k;
86         scanf("%d%d",&n,&q);
87         init();
88         while(q--)
89         {
90                 scanf("%d%d%d",&i,&j,&k);
91                 printf("%d\n",Query(i-1,j,k));
92         }
93         return 0;
94 }
95


类别:My Solution||添加到搜藏 |分享到i贴吧|浏览(573)|评论 (0)
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu