[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

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

  

    比如序列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原创 转载请注明出处

posted on 2010-08-23 00:05  Master_Chivu  阅读(4460)  评论(3编辑  收藏  举报

导航