【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.

 

posted on 2016-12-04 20:24  myx12345  阅读(191)  评论(0编辑  收藏  举报

导航