[PKU 2104 2761] 区间第k大(小)值

{

这一类问题方法很多

是练习数据结构的经典问题

建议可以线段树写一遍 用平衡树再写一遍

用树状数组也可以解决

平衡树也可以试试2种不同的方法

比如Splay和SBT

(虽然Splay不是平衡树 也不如平衡树效率高

但是Splay可以和平衡树互补解决问题

姑且笼统的把Splay归到平衡树里吧

况且很多区间问题还是少不了Splay树的

这里运用的还是平衡树的有序性 不是Splay特有的提根操作)

特殊的情况如区间最小值用RMQ解决很方便

总之 经典的题目就是和各种方法有千丝万缕的联系

需要慢慢体会

}

原题 http://acm.pku.edu.cn/JudgeOnline/problem?id=2104

   http://acm.pku.edu.cn/JudgeOnline/problem?id=2761

题意

  给定一个长为n的序列

  给定q个询问{b,' ',e,' ',k}

  求区间[b,e]内的第k小值

数据结构

  平衡树 线段树(排序树 划分树 归并树) 树状数组

 

算法

  线段树

  //建议用于解决2104

  先用线段树把归并排序的过程存下来

  [PKU 2104 2761] 区间第k大(小)值

    比如序列2 9 5 8 3 7 10 4

    如图归并的过程就记录在了一棵线段树里

    具体操作可以在建树的时候实现

    此时建树的复杂度是对每个节点进行2路归并的总复杂度

    等于x+x/2*2+x/4*4......每一层其实是一样的复杂度是O(nlog2n)

  然后是查询

    查询可以用二分答案来实现

    对于一个区间[b,e] 我们对序列内的数进行二分

    设当前二分得的答案是Mid

    我们仅需解决Mid在[b,e]内的排名Rank即可

      调用Get函数可以解决这个问题

      由于每个节点内元素有序 所以Get函数内置二分查找 用于查找给定节点内的Mid值

      如果所查区间完全包含于[b,e]则直接查找

      否则递归查找子结点中Mid值的排位累加就是在[b,e]内的排位了

      这里需要注意一点细节

      如果所查元素不在所查序列中 则排位是假设插入之后的排位

        例如在{2 3 4 5 8}中9排6,7排5,2排1......

      元素x在A序列排位a 在B序列排位b 则在AB归并后应排在a+b-1处 即累加要注意减1

        给个例子吧 A={2 3 4} B={5 7 8} x=6

        则a=4 b=2 所以6在AB归并后序列{2 3 4 5 7 8}里排第5大

    Get值返回后用于确定继续二分还是返回答案

    注意有时Get返回值为k时 Mid可以不在[b,e]中 需要判断

  最后即可得到答案

  平衡树

  //建议用来解决2761 还少讨论一种情况

  平衡树的思想相对好理解

  将所查区间存下来 按头排序 依次查询

  平衡树内保存当前查询的值

  分三种情况讨论

    第一种是前一个区间和当前区间不相交

      则删除前一个区间内所有元素 插入当前区间所有元素

    第二种是相交但不包含

      则删除前一个区间除交集以外的部分 插入当前区间除交集以外的部分

    第三种是区间为包含关系

      则删除前一个区间出交集以外的所有部分(一前一后)

    //在2761内可以不讨论最后一个情况

  讨论三种情况相当于除去了很多冗余计算 也算一个强剪枝

  (具体有多强需要数学帝考证 ms用柯西不等式外加微分法求函数极值可以解决--纯属感觉)

  查找符合Rank值要求的数时直接利用平衡树进行select操作即可

  树状数组

  //这个我只是了解一下算法 没有写

  有一个大神的算法好像是这样的

  不知道有没有歪解

  先离散化 用1-n离散n个数

  对于区间[b,e]的查询 设前一个区间为[b0,e0]

  先依次删除[b0,e0]内的每个数i 即{insert(i,-1)}

  再插入区间[b,e]内的每个数i即{insert(i,1)}

  随后sum[x]-sum[x-1]就是第x个数的排位了

  (数组里存数的个数 运用了计数排序的思想)

  同样运用二分答案解决问题

  需要注意输答案的时候不要把离散后的数输出去 要还原一下

  //好像由于常数相当小 比前2个算法还快

 

我的程序

 

 

SortTree
   
     
1 const max = 500000 ;
2   var w,c,l,r,ls,rs,id: array [ 1 ..max] of longint;
3 d: array [ 1 .. 20 , 0 ..max] of longint;
4 n,m,i,t,l0,r0,rank,s,k:longint;
5 mid:longint;
6   procedure build(a,b,dep:longint);
7   var x,y,l1,l2,i,j,p,q:longint;
8   begin
9 inc(t); x: = t;
10 l[x]: = a; r[x]: = b;
11   if b - a = 1
12 then begin inc(d[dep][ 0 ]); id[x]: = d[dep][ 0 ];
13 d[dep][id[x]]: = c[r[x]]; exit; end
14 else begin
15 y: = (a + b)shr 1 ;
16 ls[x]: = t + 1 ; build(a,y,dep + 1 );
17 rs[x]: = t + 1 ; build(y,b,dep + 1 );
18 end ;
19 id[x]: = d[dep][ 0 ] + 1 ;
20 k: = d[dep][ 0 ]; i: = id[ls[x]]; j: = id[rs[x]]; p: = ls[x]; q: = rs[x];
21 l1: = r[p] - l[p] + i - 1 ; l2: = r[q] - l[q] + j - 1 ;
22   while (i <= l1) and (j <= l2) do
23 if d[dep + 1 ][i] < d[dep + 1 ][j]
24 then begin inc(k); d[dep][k]: = d[dep + 1 ][i]; inc(i); end
25 else begin inc(k); d[dep][k]: = d[dep + 1 ][j]; inc(j); end ;
26   if i > l1 then while j <= l2 do
27 begin inc(k); d[dep][k]: = d[dep + 1 ][j]; inc(j); end ;
28   if j > l2 then while i <= l1 do
29 begin inc(k); d[dep][k]: = d[dep + 1 ][i]; inc(i); end ;
30 d[dep][ 0 ]: = k;
31   end ;
32   function get(v,x,dep:longint):longint;
33   var l0,r0,mid:longint;
34   begin
35 get: = 1 ;
36   if (s <= l[x]) and (r[x] <= t)
37 then begin
38 l0: = id[x]; r0: = id[x] + r[x] - l[x] - 1 ;
39 while l0 <= r0 do
40 begin
41 mid: = (l0 + r0)shr 1 ;
42 if d[dep][mid] = v then break;
43 if d[dep][mid] < v then l0: = mid + 1 ;
44 if d[dep][mid] > v then r0: = mid - 1 ;
45 end ;
46 if d[dep][mid] = v then exit(mid - id[x] + 1 );
47 if d[dep][mid] < v then exit(mid - id[x] + 2 );
48 if d[dep][mid] > v then exit(mid - id[x] + 1 );
49 end
50 else begin
51 mid: = (l[x] + r[x])shr 1 ;
52 if s < mid then get: = get + get(v,ls[x],dep + 1 ) - 1 ;
53 if t > mid then get: = get + get(v,rs[x],dep + 1 ) - 1 ;
54 end ;
55   end ;
56   begin
57 assign(input, ' kth.in ' );
58 reset(input);
59 assign(output, ' kth.out ' );
60 rewrite(output);
61 readln(n,m);
62   for i: = 1 to n do
63 read(c[i]);
64 t: = 0 ;
65 build( 0 ,n, 1 );
66   for i: = 1 to n do
67 begin
68 l0: = 1 ; r0: = n;
69 while l0 <= r0 do
70 begin
71 mid: = (l0 + r0)shr 1 ;
72 if d[ 1 ][mid] < c[i] then l0: = mid + 1 ;
73 if d[ 1 ][mid] = c[i] then break;
74 if d[ 1 ][mid] > c[i] then r0: = mid - 1 ;
75 end ;
76 w[mid]: = i;
77 end ;
78   for i: = 1 to m do
79 begin
80 readln(s,t,k);
81 s: = s - 1 ;
82 l0: = 1 ; r0: = n;
83 while l0 <= r0 do
84 begin
85 mid: = (l0 + r0)shr 1 ;
86 rank: = get(d[ 1 ][mid], 1 , 1 );
87 if (rank = k) and (w[mid] <= t) and (w[mid] >= s + 1 )
88 then begin writeln(d[ 1 ][mid]); break; end ;
89 if rank <= k then l0: = mid + 1 else r0: = mid - 1 ;
90 end ;
91 end ;
92 close(input);close(output);
93   end .
94  

 

 

 

SBT
   
     
1 const maxn = 400000 ;
2 maxq = 50000 ;
3   var s,l,r,n: array [ 0 ..maxn] of longint;
4 a: array [ 1 ..maxn] of longint;
5 ans,b,e,k,id: array [ 0 ..maxq] of longint;
6 last,m,q,i,j,t,tt:longint;
7   procedure zig( var x:longint);
8   var y:longint;
9   begin
10 y: = l[x]; l[x]: = r[y]; r[y]: = x;
11 s[y]: = s[x]; s[x]: = s[l[x]] + s[r[x]] + 1 ;
12 x: = y;
13   end ;
14   procedure zag( var x:longint);
15   var y:longint;
16   begin
17 y: = r[x]; r[x]: = l[y]; l[y]: = x;
18 s[y]: = s[x]; s[x]: = s[l[x]] + s[r[x]] + 1 ;
19 x: = y;
20   end ;
21   procedure maintain( var x:longint; flag:boolean);
22   begin
23   if flag
24 then begin
25 if s[l[l[x]]] > s[r[x]] then zig(x)
26 else if s[l[r[x]]] > s[r[x]]
27 then begin zag(l[x]); zig(x); end
28 else exit;
29 end
30 else begin
31 if s[r[r[x]]] > s[l[x]] then zag(x)
32 else if s[r[l[x]]] > s[l[x]]
33 then begin zig(r[x]); zag(x); end
34 else exit;
35 end ;
36 maintain(l[x],true); maintain(r[x],false);
37 maintain(x,true); maintain(x,false);
38   end ;
39   procedure insert( var x:longint; v:longint);
40   begin
41   if x = 0
42 then begin
43 inc(tt); x: = tt;
44 s[x]: = 1 ; n[x]: = v;
45 l[x]: = 0 ; r[x]: = 0 ;
46 end
47 else begin
48 inc(s[x]);
49 if v <= n[x]
50 then insert(l[x],v)
51 else insert(r[x],v);
52 maintain(x,v <= n[x]);
53 end ;
54   end ;
55   function delete( var x:longint; v:longint):longint;
56   begin
57   if x = 0 then exit;
58 dec(s[x]);
59   if (l[x] = 0 ) and (v < n[x]) or (r[x] = 0 ) and (v > n[x]) or (v = n[x])
60 then begin
61 delete: = n[x];
62 if (l[x] = 0 ) or (r[x] = 0 )
63 then x: = l[x] + r[x]
64 else n[x]: = delete(l[x],n[x] + 1 );
65 end
66 else if v < n[x]
67 then delete: = delete(l[x],v)
68 else delete: = delete(r[x],v);
69   end ;
70   function select(x,k:longint):longint;
71   begin
72   if k = s[l[x]] + 1
73 then exit(n[x]);
74   if k <= s[l[x]]
75 then select: = select(l[x],k)
76 else select: = select(r[x],k - s[l[x]] - 1 );
77   end ;
78   procedure sort(l,r:longint);
79   var i,j,x,y:longint;
80   begin
81 i: = l; j: = r;
82 x: = b[(l + r)shr 1 ];
83   repeat
84   while b[i] < x do inc(i);
85   while b[j] > x do dec(j);
86   if not (i > j)
87 then begin
88 y: = b[i]; b[i]: = b[j]; b[j]: = y;
89 y: = e[i]; e[i]: = e[j]; e[j]: = y;
90 y: = k[i]; k[i]: = k[j]; k[j]: = y;
91 y: = id[i]; id[i]: = id[j]; id[j]: = y;
92 inc(i); dec(j);
93 end ;
94 until i > j;
95 if i < r then sort(i,r);
96 if l < j then sort(l,j);
97 end ;
98 procedure sortback(l,r:longint);
99 var i,j,x,y:longint;
100 begin
101 i: = l; j: = r;
102 x: = id[(l + r)shr 1 ];
103 repeat
104 while id[i] < x do inc(i);
105 while id[j] > x do dec(j);
106 if not (i > j)
107 then begin
108 y: = b[i]; b[i]: = b[j]; b[j]: = y;
109 y: = e[i]; e[i]: = e[j]; e[j]: = y;
110 y: = k[i]; k[i]: = k[j]; k[j]: = y;
111 y: = id[i]; id[i]: = id[j]; id[j]: = y;
112 y: = ans[i]; ans[i]: = ans[j]; ans[j]: = y;
113 inc(i); dec(j);
114 end ;
115 until i > j;
116 if i < r then sortback(i,r);
117 if l < j then sortback(l,j);
118 end ;
119 procedure out(x:longint);
120 begin
121 if x = 0 then exit;
122 out(l[x]);
123 write(n[x], ' ' );
124 out(r[x]);
125 end ;
126 begin
127 assign(input, ' feed.in ' ); reset(input);
128 assign(output, ' feed.out ' ); rewrite(output);
129 readln(m,q);
130 for i: = 1 to m do
131 read(a[i]);
132 for i: = 1 to q do
133 begin
134 id[i]: = i;
135 readln(b[i],e[i],k[i]);
136 end ;
137 sort( 1 ,q);
138 tt: = 0 ; t: = 0 ; s[ 0 ]: = 0 ;
139 b[ 0 ]: = 0 ; e[ 0 ]: = 0 ;
140 for i: = 1 to q do
141 begin
142 if e[i - 1 ] < b[i]
143 then begin
144 for j: = b[i - 1 ] to e[i - 1 ] do
145 delete(t,a[j]);
146 for j: = b[i] to e[i] do
147 insert(t,a[j]);
148 end
149 else if e[i - 1 ] < e[i]
150 then begin
151 for j: = b[i - 1 ] to b[i] - 1 do
152 delete(t,a[j]);
153 for j: = e[i - 1 ] + 1 to e[i] do
154 insert(t,a[j]);
155 end
156 else begin
157 for j: = b[i - 1 ] to b[i] - 1 do
158 delete(t,a[j]);
159 for j: = e[i] + 1 to e[i - 1 ] do
160 delete(t,a[j]);
161 end ;
162 ans[i]: = select(t,k[i]);
163 // out(t);writeln
164 end ;
165 sortback( 1 ,q);
166 for i: = 1 to q do
167 writeln(ans[i]);
168 close(input); close(output);
169 end .
170

 

 

//大神的Splay 是yzhw写了之后 mq_miqing改成数组模拟指针的很不错

 

Splay
   
     
1 program PKU_ 2761 _Feed_the_dogs;
2
3 const
4 maxN = 1000000 ; // 这里我开的10n过的,应该是多少我不清楚,望神牛解答
5 maxM = 50000 ;
6
7 type
8 TQuery = record
9 l,r,k,id:longint
10 end ;
11
12 var
13 n,m,root,numNode:longint;
14 a,left,right,fa,key,size: array [ 0 ..maxN] of longint;
15 q: array [ 1 ..maxM] of TQuery;
16 ans: array [ 1 ..maxM] of longint;
17
18 function leftRotate(i:longint):longint;
19 var
20 j:longint;
21 begin
22 j: = right[i];
23 right[i]: = left[j];
24 left[j]: = i;
25 fa[j]: = fa[i];
26 fa[i]: = j;
27 if right[i] <> 0 then fa[right[i]]: = i;
28 size[j]: = size[i];
29 size[i]: = size[left[i]] + size[right[i]] + 1 ;
30 exit(j);
31 end ;
32
33 function rightRotate(i:longint):longint;
34 var
35 j:longint;
36 begin
37 j: = left[i];
38 left[i]: = right[j];
39 right[j]: = i;
40 fa[j]: = fa[i];
41 fa[i]: = j;
42 if left[i] <> 0 then fa[left[i]]: = i;
43 size[j]: = size[i];
44 size[i]: = size[left[i]] + size[right[i]] + 1 ;
45 exit(j);
46 end ;
47
48 function newNode(f,k:longint):longint;
49 begin
50 inc(numNode);
51 key[numNode]: = k;
52 fa[numNode]: = f;
53 size[numNode]: = 1 ;
54 exit(numNode);
55 end ;
56
57 procedure splay(i:longint);
58 var
59 f,g:longint;
60 pg:^longint;
61 begin
62 while fa[i] <> 0 do begin
63 f: = fa[i];
64 g: = fa[f];
65 if g = 0 then begin
66 if i = left[f] then root: = rightRotate(f)
67 else root: = leftRotate(f);
68 break;
69 end ;
70 if fa[g] = 0 then pg: = @root
71 else if g = left[fa[g]] then pg: = @left[fa[g]]
72 else pg: = @right[fa[g]];
73 if f = left[g] then begin
74 if i = left[f] then begin
75 pg^: = rightRotate(g);
76 pg^: = rightRotate(f);
77 end else begin
78 left[g]: = leftRotate(f);
79 pg^: = rightRotate(g);
80 end ;
81 end else begin
82 if i = right[f] then begin
83 pg^: = leftRotate(g);
84 pg^: = leftRotate(f);
85 end else begin
86 right[g]: = rightRotate(f);
87 pg^: = leftRotate(g);
88 end ;
89 end ;
90 end ;
91 end ;
92
93 procedure insert(k:longint);
94 var
95 i,j:longint;
96 begin
97 if root = 0 then begin
98 root: = newNode( 0 ,k);
99 exit;
100 end ;
101 i: = root;
102 inc(size[root]);
103 if k < key[i] then j: = left[i] else j: = right[i];
104 while j <> 0 do begin
105 inc(size[j]);
106 i: = j;
107 if k < key[j] then j: = left[j] else j: = right[j];
108 end ;
109 if k < key[i] then begin
110 left[i]: = newNode(i,k);
111 splay(left[i]);
112 end else begin
113 right[i]: = newNode(i,k);
114 splay(right[i]);
115 end ;
116 end ;
117
118 function union(a,b:longint):longint;
119 var
120 i,j:longint;
121 begin
122 i: = a;
123 while right[i] <> 0 do i: = right[i];
124 splay(i);
125 j: = b;
126 while left[j] <> 0 do j: = left[j];
127 splay(j);
128 fa[i]: = j;
129 inc(size[j],size[i]);
130 left[j]: = i;
131 exit(j);
132 end ;
133
134 procedure delete(k:longint);
135 var
136 i,l,r:longint;
137 begin
138 i: = root;
139 while key[i] <> k do
140 if k < key[i] then i: = left[i] else i: = right[i];
141 splay(i);
142 if (left[i] = 0 ) and (right[i] = 0 ) then root: = 0
143 else if left[i] = 0 then begin root: = right[i]; fa[right[i]]: = 0 ; end
144 else if right[i] = 0 then begin root: = left[i]; fa[left[i]]: = 0 ; end
145 else begin
146 l: = left[i]; r: = right[i];
147 fa[l]: = 0 ; fa[r]: = 0 ; root: = 0 ;
148 root: = union(l,r);
149 end ;
150 key[i]: =- 1 ;
151 end ;
152
153 function select(k:longint):longint;
154 var
155 i:longint;
156 begin
157 i: = root;
158 while k <> size[left[i]] + 1 do
159 if k < size[left[i]] + 1 then i: = left[i] else begin
160 dec(k,size[left[i]] + 1 );
161 i: = right[i];
162 end ;
163 exit(key[i]);
164 end ;
165
166 function lessThan( var a,b:TQuery):boolean;
167 begin
168 if a.l < b.l then exit(true)
169 else if a.l > b.l then exit(false)
170 else if a.r > b.r then exit(true)
171 else exit(false);
172 end ;
173
174 procedure qSort(l,r:longint);
175 var
176 i,j:longint;
177 x,tmp:TQuery;
178 begin
179 i: = l; j: = r; x: = q[(i + j) >> 1 ];
180 repeat
181 while lessThan(q[i],x) do inc(i);
182 while lessThan(x,q[j]) do dec(j);
183 if i <= j then begin
184 tmp: = q[i]; q[i]: = q[j]; q[j]: = tmp;
185 inc(i); dec(j);
186 end ;
187 until i > j;
188 if i < r then qSort(i,r);
189 if j > l then qSort(l,j);
190 end ;
191
192 procedure init;
193 var
194 i:longint;
195 begin
196 assign(input, ' kth.in ' ); reset(input);
197 assign(output, ' kth.out ' ); rewrite(output);
198 readln(n,m);
199 for i: = 1 to n do read(a[i]);
200 readln;
201 for i: = 1 to m do
202 with q[i] do begin
203 readln(l,r,k);
204 id: = i;
205 end ;
206 qSort( 1 ,m);
207 end ;
208
209 function max(a,b:longint):longint;
210 begin if a > b then exit(a) else exit(b); end ;
211
212 function min(a,b:longint):longint;
213 begin if a < b then exit(a) else exit(b); end ;
214
215 procedure main;
216 var
217 i,j:longint;
218 begin
219 for j: = q[ 1 ].l to q[ 1 ].r do
220 insert(a[j]);
221 ans[q[ 1 ].id]: = select(q[ 1 ].k);
222 for i: = 2 to m do begin
223 if q[i].l > q[i - 1 ].r then begin
224 for j: = q[i - 1 ].l to q[i - 1 ].r do delete(a[j]);
225 for j: = q[i].l to q[i].r do insert(a[j]);
226 end else if (q[i].l <= q[i - 1 ].r) and (q[i].r > q[i - 1 ].r) then begin
227 for j: = q[i - 1 ].r + 1 to q[i].r do insert(a[j]);
228 for j: = q[i - 1 ].l to q[i].l - 1 do delete(a[j]);
229 end else begin
230 for j: = q[i - 1 ].l to q[i].l - 1 do delete(a[j]);
231 for j: = q[i].r + 1 to q[i - 1 ].r do delete(a[j]);
232 end ;
233 ans[q[i].id]: = select(q[i].k);
234 end ;
235 end ;
236
237 procedure print;
238 var
239 i:longint;
240 begin
241 for i: = 1 to m do writeln(ans[i]);
242 end ;
243
244 begin
245 init;
246 main;
247 print;
248 close(input); close(output);
249 end .

 

 

一题多练是很爽的啊

p.s. SBT确实快1700+ms Splay是3000+ms 看来Splay树的优越性确实不在作为平衡树使用

  换句话说 拿Splay和其他平衡树比较是相当不公平不合理的 发扬光大Splay独有的Splay操作才是硬道理

 

BOB HAN原创 转载请注明出处

你可能感兴趣的:(pku)