【BZOJ2733】永无乡(线段树,启发式合并)
题意:支持合并,求块内K小数
对于 100%的数据 n≤100000,m≤n,q≤300000
思路:对于每一个块建立一棵动态开点的线段树,暴力(启发式?)合并后二分下就行了
merge用函数的方式写因为懒得讨论x,y其中一个为0的情况,反正是把节点y并到x上
为什么这么暴力都不T?大概是因为随机数据的块的大小太平均了吧
1 var t:array[0..2100000,0..1]of longint; 2 sum:array[0..2100000]of longint; 3 fa,a,root:array[0..300000]of longint; 4 n,m,x,y,k,i,j,s,cnt,p,q:longint; 5 ch:string; 6 7 function find(k:longint):longint; 8 begin 9 if fa[k]<>k then fa[k]:=find(fa[k]); 10 exit(fa[k]); 11 end; 12 13 procedure pushup(x:longint); 14 var l,r:longint; 15 begin 16 l:=t[x,0]; r:=t[x,1]; 17 sum[x]:=sum[l]+sum[r]; 18 end; 19 20 procedure update(l,r,x:longint;var p:longint); 21 var mid:longint; 22 begin 23 if p=0 then 24 begin 25 inc(cnt); p:=cnt; 26 end; 27 if l=r then 28 begin 29 inc(sum[p]); exit; 30 end; 31 mid:=(l+r)>>1; 32 if x<=mid then update(l,mid,x,t[p,0]) 33 else update(mid+1,r,x,t[p,1]); 34 pushup(p); 35 end; 36 37 function merge(x,y:longint):longint; 38 var mid:longint; 39 begin 40 if (x=0)or(y=0) then exit(x+y); 41 t[x,0]:=merge(t[x,0],t[y,0]); 42 t[x,1]:=merge(t[x,1],t[y,1]); 43 pushup(x); 44 exit(x); 45 end; 46 47 48 function query(l,r,k,p:longint):longint; 49 var mid,tmp:longint; 50 begin 51 if sum[p]<k then exit(-1); 52 if l=r then exit(a[l]); 53 tmp:= sum[t[p,0]]; 54 mid:=(l+r)>>1; 55 if tmp>=k then exit(query(l,mid,k,t[p,0])) 56 else exit(query(mid+1,r,k-tmp,t[p,1])); 57 end; 58 59 begin 60 assign(input,'bzoj2733.in'); reset(input); 61 assign(output,'bzoj2733.out'); rewrite(output); 62 readln(n,m); 63 for i:=1 to n do 64 begin 65 read(x); a[x]:=i; 66 update(1,n,x,root[i]); 67 end; 68 for i:=1 to n do fa[i]:=i; 69 for i:=1 to m do 70 begin 71 readln(x,y); 72 p:=find(x); q:=find(y); 73 if p<>q then 74 begin 75 fa[q]:=p; 76 merge(root[p],root[q]); 77 end; 78 end; 79 readln(m); 80 for i:=1 to m do 81 begin 82 readln(ch); 83 s:=0; x:=0; y:=0; k:=length(ch); 84 for j:=2 to k do 85 begin 86 if ch[j]=' ' then begin inc(s); continue; end; 87 if s=1 then x:=x*10+ord(ch[j])-ord('0'); 88 if s=2 then y:=y*10+ord(ch[j])-ord('0'); 89 end; 90 case ch[1] of 91 'Q':writeln(query(1,n,y,root[find(x)])); 92 'B': 93 begin 94 p:=find(x); q:=find(y); 95 if p<>q then 96 begin 97 fa[q]:=p; root[p]:=merge(root[p],root[q]); 98 end; 99 end; 100 end; 101 end; 102 103 104 close(input); 105 close(output); 106 end.
null