算法的学习没有尽头!前面还有无尽远的路!
前两天做一道题的时候看到划分树,找到小航航大牛的博客看了一下,很神奇的算法,总的来说就是一个逆归并的过程,从大到小的归并排序,建立线段树,记录每个区间中被分到左子树的数据,然后查询的时候就可以用log(n)的时间查询任意区间第K大数了。由于本人缺乏创新性,代码严重抄袭小航航牛,不再赘述!
回头用划分树做了北大的2104和杭电的3473,速度还算可以,这里仅给出3473的代码以供参考!
1 #include < stdio.h >
2 #include < string .h >
3 #include < stdlib.h >
4 #define M 100005
5 struct Node{
6 int l,r;
7 } Tree[M * 4 ];
8 int sorted[M],toleft[ 20 ][M],val[ 20 ][M];
9 __int64 sum[M],tolsum[ 20 ][M];
10 __int64 lsum,rsum;
11 int cmp( const void * a, const void * b)
12 { return * ( int * )a - * ( int * )b; }
13 void build( int l, int r, int d, int idx)
14 {
15 Tree[idx].l = l; Tree[idx].r = r;
16 if (l == r) return ;
17 int i,mid = (l + r) >> 1 ,midv = sorted[mid];
18 int lsame = mid - l + 1 ;
19 for (i = l; i <= r; i ++ ) if (val[d][i] < midv) lsame -- ;
20 int lpos = l, rpos = mid + 1 , same = 0 ;
21 for (i = l; i <= r; i ++ ){
22 if (i == l){
23 toleft[d][i] = 0 ; tolsum[d][i] = 0 ;
24 }
25 else {
26 toleft[d][i] = toleft[d][i - 1 ]; tolsum[d][i] = tolsum[d][i - 1 ];
27 }
28 if (val[d][i] < midv){
29 toleft[d][i] ++ ; val[d + 1 ][lpos ++ ] = val[d][i];
30 tolsum[d][i] += val[d][i];
31 }
32 else if (val[d][i] > midv) val[d + 1 ][rpos ++ ] = val[d][i];
33 else {
34 if (same < lsame){
35 same ++ ; toleft[d][i] ++ ; val[d + 1 ][lpos ++ ] = val[d][i];
36 tolsum[d][i] += val[d][i];
37 }
38 else val[d + 1 ][rpos ++ ] = val[d][i];
39 }
40 }
41 build(l,mid,d + 1 ,idx << 1 );
42 build(mid + 1 ,r,d + 1 ,(idx << 1 ) + 1 );
43 }
44 int query( int l, int r, int k, int d, int idx)
45 {
46 if (l == r) return val[d][l];
47 int tol;
48 int stol;
49 __int64 cntl;
50 if (l == Tree[idx].l){
51 stol = 0 ; tol = toleft[d][r];
52 cntl = 0 ;
53 } else {
54 stol = toleft[d][l - 1 ]; tol = toleft[d][r] - stol;
55 cntl = tolsum[d][l - 1 ];
56 }
57 if (tol >= k){
58 int start = Tree[idx].l + stol, end = start + tol - 1 ;
59
60 return query(start,end,k,d + 1 ,idx << 1 );
61 } else {
62 lsum += tolsum[d][r] - cntl;
63 int mid = (Tree[idx].l + Tree[idx].r) >> 1 ;
64 int tor = r - l - tol + 1 ;
65 int stor = l - Tree[idx].l - stol;
66 return query(mid + 1 + stor,mid + stor + tor,k - tol,d + 1 ,(idx << 1 ) + 1 );
67 }
68 }
69 int main()
70 {
71 int ncase,cas,i,k,n,m;
72 scanf ( " %d " , & ncase);
73 for (cas = 1 ; cas <= ncase; cas ++ ){
74 sum[ 0 ] = 0 ;
75 scanf ( " %d " , & n);
76 for (i = 1 ; i <= n; i ++ ){
77 scanf ( " %d " , & val[ 0 ][i]);
78 sorted[i] = val[ 0 ][i];
79 sum[i] = sum[i - 1 ] + sorted[i];
80 }
81 qsort(sorted + 1 ,n, sizeof (sorted[ 0 ]),cmp);
82 build( 1 ,n, 0 , 1 );
83 scanf ( " %d " , & m);
84 printf ( " Case #%d:\n " ,cas);
85 for (i = 0 ; i < m; i ++ ){
86 int s,e;
87 scanf ( " %d%d " , & s, & e);
88 s ++ ; e ++ ;
89 int num = e - s + 1 ;
90 k = num / 2 ; if (num % 2 != 0 ) k ++ ;
91 lsum = 0 ;
92 rsum = sum[e] - sum[s - 1 ];
93 int ans = query(s,e,k, 0 , 1 );
94 rsum -= ans; rsum -= lsum;
95 __int64 re = (__int64)(k - 1 ) * (__int64)ans - lsum + rsum - (__int64)(num - k) * (__int64)ans;
96 printf ( " %I64d\n " ,re);
97 }
98 printf ( " \n " );
99 }
100 return 0 ;
101 }
dp和联通分量,下一阶段的目标,路漫漫谁与我同行,水长长自有人同舟!