标签:des style blog class code java
Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 35653 | Accepted: 11382 | |
Case Time Limit: 2000MS |
Description
Input
Output
Sample Input
7 3 1 5 2 6 3 7 4 2 5 3 4 4 1 1 7 3
Sample Output
5 6 3
Hint
Source
1 #include <iostream>
2 #include <stdio.h>
3 #include <algorithm>
4 using namespace std;
5 #define MAXN 100005
6 struct Divide_tree{ //划分树的结构(4个数组,2个操作)
7 int arr[MAXN]; //原数组
8 int sorted[MAXN]; //排序后数组
9 int sum[20][MAXN]; //记录第i层1~j划分到左子树的元素个数(包括j)
10 int dat[20][MAXN]; //记录第i层元素序列
11 void build(int c,int L,int R) //建树,主要是建立sum[][]和dat[][]数组
12 {
13 int mid = (L+R)>>1;
14 int lsame = mid-L+1; //lsame用来记录和中间值val_mid相等的,且可以分到左孩子的数的个数
15 //简单来说就是可以放入左孩子的,与中间值val_mid相等的数的个数
16 int lp=L,rp=mid+1; //当前节点的左孩子和右孩子存数的起点
17 for(int i=L;i<mid;i++) //获得一开始的lsame
18 if(sorted[i]<sorted[mid])
19 lsame--;
20 for(int i=L;i<=R;i++){ //从前往后遍历一遍,
21 //确定当前节点区间内的所有元素的归属(放在左孩子或者放在右孩子)
22 if(i==L) sum[c][i]=0;
23 else sum[c][i]=sum[c][i-1];
24 if(dat[c][i]<sorted[mid]){ //当前元素比中间值val_mid小,放入左孩子
25 dat[c+1][lp++] = dat[c][i];
26 sum[c][i]++;
27 }
28 else if(dat[c][i]>sorted[mid]) //当前元素比中间值val_mid大,放入右孩子
29 dat[c+1][rp++] = dat[c][i];
30 else{ //当前元素值与中间值val_mid相等,根据lsame数判断放入左孩子还是右孩子
31 if(lsame){
32 lsame--;
33 sum[c][i]++;
34 dat[c+1][lp++]=sorted[mid];
35 }
36 else{
37 dat[c+1][rp++]=sorted[mid];
38 }
39 }
40 }
41 if(L==R) return ; //递归出口,遇到叶子节点
42 build(c+1,L,mid); //递归进入左孩子区间
43 build(c+1,mid+1,R); //递归进入右孩子区间
44 }
45 int query(int c,int L,int R,int ql,int qr,int k)
46 {
47 //c为树的层数,L,R为当前节点的区间范围,ql,qr为查询的区间范围,k为查询范围内第k大的数
48 if(L==R) //递归出口,返回第k大的数
49 return dat[c][L];
50 int s; //记录[L,ql-1]中进入左孩子的元素的个数
51 int ss; //记录[ql,qr]中进入左孩子的元素的个数
52 int mid=(L+R)>>1;
53 if(L==ql){ //端点重合的情况,单独考虑
54 s=0;
55 ss=sum[c][qr];
56 }
57 else {
58 s=sum[c][ql-1];
59 ss=sum[c][qr]-s;
60 }
61 if(k<=ss) //左孩子的元素个数大于k个,说明第k大的元素一定在左孩子区间中,到左孩子中查询
62 return query(c+1,L,mid,L+s,L+s+ss-1,k);
63 else
64 return query(c+1,mid+1,R,mid+1+ql-s-L,mid+1+qr-s-ss-L,k-ss);
65 }
66 };
67 Divide_tree tree; //定义划分树
68 int main()
69 {
70 int i,L,R,N,M,k;
71 scanf("%d%d",&N,&M);
72 for(i=1;i<=N;i++){ //输入
73 scanf("%d",&tree.arr[i]);
74 tree.sorted[i]=tree.dat[0][i]=tree.arr[i];
75 }
76 sort(tree.sorted+1,tree.sorted+N+1);
77 tree.build(0,1,N);
78 for(i=1;i<=M;i++){ //M次询问
79 scanf("%d%d%d",&L,&R,&k);
80 printf("%d\n",tree.query(0,1,N,L,R,k));
81 }
82
83 return 0;
84 }
poj 2104:K-th Number(划分树,经典题),布布扣,bubuko.com
标签:des style blog class code java
原文地址:http://www.cnblogs.com/yym2013/p/3714654.html