bzoj 1901 线段树套平衡树+二分答案查询
我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案,
查询每个二分到的mid在这个区间里的rank,然后就行了
/************************************************************** Problem: 1901 User: BLADEVIL Language: Pascal Result: Accepted Time:3220 ms Memory:6592 kb ****************************************************************/ //By BLADEVIL type rec =record left, right, root :longint; end; var n, m :longint; a :array[0..10010] of longint; t :array[0..40010] of rec; bt :array[0..300000] of longint; b_size, b_left, b_right :array[0..300000] of longint; b_key :array[0..300000] of longint; tot :longint; function min(a,b:longint):longint; begin if a>b then min:=b else min:=a; end; function max(a,b:longint):longint; begin if a>b then max:=a else max:=b; end; procedure rotate_right(var t:longint); var k :longint; begin k:=b_left[t]; b_left[t]:=b_right[k]; b_right[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[b_right[t]]+b_size[b_left[t]]+1; t:=k; end; procedure rotate_left(var t:longint); var k :longint; begin k:=b_right[t]; b_right[t]:=b_left[k]; b_left[k]:=t; b_size[k]:=b_size[t]; b_size[t]:=b_size[b_right[t]]+b_size[b_left[t]]+1; t:=k; end; procedure maintain(var t:longint; flag:boolean); begin if not flag then begin if b_size[b_left[b_left[t]]]>b_size[b_right[t]] then rotate_right(b_left[t]) else if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then begin rotate_left(b_left[t]); rotate_right(t); end else exit; end else begin if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then rotate_left(b_right[t]) else if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then begin rotate_right(b_right[t]); rotate_left(t); end else exit; end; maintain(b_left[t],false); maintain(b_right[t],true); maintain(t,true); maintain(t,false); end; procedure insert(var t:longint; v:longint); begin if t=0 then begin inc(tot); t:=tot; b_left[t]:=0; b_right[t]:=0; b_size[t]:=1; b_key[t]:=v; end else begin inc(b_size[t]); if v>=b_key[t] then insert(b_right[t],v) else insert(b_left[t],v); maintain(t,v>=b_key[t]); end; end; function delete(var t:longint; v:longint):longint; begin dec(b_size[t]); if (b_key[t]=v) or (b_right[t]=0) and (v>b_key[t]) or (b_left[t]=0) and (v<b_key[t]) then begin delete:=b_key[t]; if (b_left[t]=0) or (b_right[t]=0) then t:=b_right[t]+b_left[t] else b_key[t]:=delete(b_left[t],v+1); end else if v<b_key[t] then delete:=delete(b_left[t],v) else delete:=delete(b_right[t],v); end; function rank(var t:longint; v:longint):longint; begin if t=0 then exit(0); if v<=b_key[t] then rank:=rank(b_left[t],v) else rank:=rank(b_right[t],v)+b_size[b_left[t]]+1; end; procedure build(x,l,r:longint); var mid :longint; i :longint; begin t[x].left:=l; t[x].right:=r; t[x].root:=0; for i:=l to r do insert(t[x].root,a[i]); if l=r then exit; mid:=(l+r) div 2; build(x*2,l,mid); build(x*2+1,mid+1,r); end; procedure change(x,y,z:longint); var mid :longint; begin mid:=delete(t[x].root,a[y]); insert(t[x].root,z); if t[x].left=t[x].right then exit; with t[x] do mid:=(left+right) div 2; if y>mid then change(x*2+1,y,z) else change(x*2,y,z); end; function ask(x,l,r,k:longint):longint; var mid :longint; begin ask:=0; if (t[x].left=l) and (t[x].right=r) then begin ask:=rank(t[x].root,k); exit; end; with t[x] do mid:=(left+right) div 2; if mid<l then ask:=ask(x*2+1,l,r,k) else if mid>=r then ask:=ask(x*2,l,r,k) else ask:=ask(x*2,l,mid,k)+ask(x*2+1,mid+1,r,k); end; function succ(var t:longint;v:longint):longint; begin if t=0 then exit(-1); if b_key[t]<v then succ:=succ(b_right[t],v) else begin succ:=succ(b_left[t],v); if succ=-1 then succ:=b_key[t]; end; end; function pred(var t:longint;v:longint):longint; begin if t=0 then exit(-1); if b_key[t]>v then pred:=pred(b_left[t],v) else begin pred:=pred(b_right[t],v); if pred=-1 then pred:=b_key[t]; end; end; function ask_succ(x,l,r,y:longint):longint; var mid :longint; begin if (t[x].left=l) and (t[x].right=r) then begin ask_succ:=succ(t[x].root,y); if ask_succ=-1 then ask_succ:=maxlongint; exit; end; with t[x] do mid:=(left+right) div 2; if l>mid then ask_succ:=ask_succ(x*2+1,l,r,y) else if r<=mid then ask_succ:=ask_succ(x*2,l,r,y) else ask_succ:=min(ask_succ(x*2,l,mid,y),ask_succ(x*2+1,mid+1,r,y)); end; function ask_pred(x,l,r,y:longint):longint; var mid :longint; begin if (t[x].left=l) and (t[x].right=r) then begin ask_pred:=pred(t[x].root,y); exit; end; with t[x] do mid:=(left+right) div 2; if l>mid then ask_pred:=ask_pred(x*2+1,l,r,y) else if r<=mid then ask_pred:=ask_pred(x*2,l,r,y) else ask_pred:=max(ask_pred(x*2,l,mid,y),ask_pred(x*2+1,mid+1,r,y)); end; procedure query(x,y,k:longint); var l, r, mid :longint; ans :longint; xx :longint; begin l:=1; r:=1000000000; while l<=r do begin mid:=(l+r) div 2; xx:=ask(1,x,y,mid); if xx>=k-1 then begin ans:=mid; r:=mid-1; end else l:=mid+1; end; if ask(1,x,y,ans)<>k-1 then xx:=ask_pred(1,x,y,ans-1) else xx:=ask_succ(1,x,y,ans); writeln(xx); end; procedure init; var i :longint; begin read(n,m); for i:=1 to n do read(a[i]); readln; build(1,1,n); end; procedure main; var i :longint; ch :char; l, r, x :longint; begin for i:=1 to m do begin read(ch); if ch='Q' then begin readln(l,r,x); query(l,r,x); end else begin readln(l,x); change(1,l,x); a[l]:=x; end; end; end; begin init; main; end.