poj 2104 K-th Number 划分树

题意:给一个数列a[1~n],有m个询问

每次询问 [l,r]中第k小的数

 

思路:划分树

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 #define MAXN 100001
 8 struct node
 9 {
10     int val[MAXN],num[MAXN];
11 }tree[20];
12 int n,m;
13 int sorted[MAXN],a[MAXN];
14 void build(int t,int left,int right)
15 {
16     if(left==right)
17         return ;
18     int mid=(left+right)/2;
19     int i,k1=left-1,k2=mid;
20     for(i=left;i<=right;i++)
21     {
22         if(tree[t].val[i]<=sorted[mid])
23             tree[t+1].val[++k1]=tree[t].val[i];
24         else
25             tree[t+1].val[++k2]=tree[t].val[i];
26         tree[t].num[i]=k1+1-left+tree[t].num[left-1];
27     }
28     build(t+1,left,mid);
29     build(t+1,mid+1,right);
30 }
31 void search(int left,int right,int l,int r,int k,int t)
32 {
33     if(left==right)
34     {
35         printf("%d\n",tree[t].val[left]);
36         return ;
37     }
38     int mid=(left+right)/2;
39     int temp=tree[t].num[r]-tree[t].num[l-1];
40     int x=tree[t].num[l-1]-tree[t].num[left-1];
41     int y=tree[t].num[r]-tree[t].num[left-1];
42     if(temp>=k)
43     {
44         search(left,mid,left+x,left+y-1,k,t+1);
45     }
46     else
47     {
48         search(mid+1,right,mid+l-left+1-x,mid+r-left+1-y,k-temp,t+1);
49     }
50 }
51 int main()
52 {
53     memset(tree,0,sizeof(tree));
54     scanf("%d%d",&n,&m);
55     int i;
56     int x,y,z;
57     for(i=1;i<=n;i++)
58     {
59         scanf("%d",a+i);
60         sorted[i]=a[i];
61         tree[1].val[i]=a[i];
62     }
63     sort(sorted+1,sorted+n+1);
64     build(1,1,n);
65     for(i=1;i<=m;i++)
66     {
67         scanf("%d%d%d",&x,&y,&z);
68         search(1,n,x,y,z,1);
69     }
70     return 0;
71 }

posted on 2012-07-08 21:47  myoi  阅读(203)  评论(0编辑  收藏  举报

导航