【BZOJ3524】Couriers(主席树)
题意:给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
n,m≤500000
思路:这题可以用主席树巧妙地做
询问(x,y)区间时直接输出a[query(x,y)]
首先区间内个数>(r-l+1)/2的数字如果有的话有且只有一个
其次答案数字肯定在数字总和大于一半的一边
这样询问可以做到logn
离散化注意
1 var t:array[0..20000000]of record 2 l,r,s:longint; 3 end; 4 a,b,c,d,root,h:array[0..1000000]of longint; 5 n,m,i,x,y,cnt:longint; 6 7 procedure swap(var x,y:longint); 8 var t:longint; 9 begin 10 t:=x; x:=y; y:=t; 11 end; 12 13 procedure qsort(l,r:longint); 14 var i,j,mid:longint; 15 begin 16 i:=l; j:=r; mid:=a[(l+r)>>1]; 17 repeat 18 while mid>a[i] do inc(i); 19 while mid<a[j] do dec(j); 20 if i<=j then 21 begin 22 swap(a[i],a[j]); 23 swap(c[i],c[j]); 24 inc(i); dec(j); 25 end; 26 until i>j; 27 if l<j then qsort(l,j); 28 if i<r then qsort(i,r); 29 end; 30 31 procedure update(l,r:longint;var p:longint;x:longint); 32 var mid:longint; 33 begin 34 inc(cnt); t[cnt]:=t[p]; 35 p:=cnt; inc(t[p].s); 36 if l=r then exit; 37 mid:=(l+r)>>1; 38 if x<=mid then update(l,mid,t[p].l,x) 39 else update(mid+1,r,t[p].r,x); 40 end; 41 42 function query(p1,p2,l,r,k:longint):longint; 43 var mid,t1,t2:longint; 44 begin 45 if l=r then exit(l); 46 t1:=t[t[p2].l].s-t[t[p1].l].s; 47 t2:=t[t[p2].r].s-t[t[p1].r].s; 48 mid:=(l+r)>>1; 49 if t1>=k then exit(query(t[p1].l,t[p2].l,l,mid,k)) 50 else if t2>=k then exit(query(t[p1].r,t[p2].r,mid+1,r,k)) 51 else exit(0); 52 end; 53 54 begin 55 assign(input,'bzoj3524.in'); reset(input); 56 assign(output,'bzoj3524.out'); rewrite(output); 57 readln(n,m); 58 for i:=1 to n do 59 begin 60 read(a[i]); 61 b[i]:=a[i]; c[i]:=i; 62 end; 63 qsort(1,n); 64 d[c[1]]:=1; 65 for i:=2 to n do 66 if a[i]<>a[i-1] then d[c[i]]:=d[c[i-1]]+1 67 else d[c[i]]:=d[c[i-1]]; //离散化 68 for i:=1 to n do h[d[i]]:=b[i]; //离散化后还原原数 69 for i:=1 to n do 70 begin 71 root[i]:=root[i-1]; 72 update(1,n,root[i],d[i]); 73 end; 74 for i:=1 to m do 75 begin 76 readln(x,y); 77 writeln(h[query(root[x-1],root[y],1,n,(y-x+1) div 2+1)]); 78 end; 79 close(input); 80 close(output); 81 end.
null