中位数的题目一定要想到二分答案然后把所有数变成1或-1什么的。。。
先离散化,这样最多只有n个值,然后对于每个值建主席树,>=的设为1,<的设为-1。按照升序建的话每次最多更改一个值,也就是logN个点。
设询问区间[ a, b] [ c, d]为然后二分答案K,现在要求的就是在主席树的第K个版本中(b,c)的和,[ a, b]的最大右子段和,[ c, d]的最大左子段和,三个东西加起来是否大于0。所以线段树中维护sum,maxl,maxr。
maxl,maxr的求法和sum差不多,yy一下。。。
代码:
type
node=record
t,id:longint;
end;
tree=^treenode;
treenode=record
l,r,maxl,maxr,sum:longint;
ls,rs:tree;
end;
var
n,m,i,j,last,size:longint;
a:array[0..20010]of node;
b,vsn:array[0..20010]of longint;
tr:array[0..20010]of tree;
q:array[1..4]of longint;
function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
procedure qs(p,q:longint);
var
i,j:longint;
t,mid:node;
begin
i:=p;
j:=q;
mid:=a[(p+q)div 2];
repeat
while a[i].tdo inc(i);
while a[j].t>mid.t do dec(j);
if i<=j then
begin
t:=a[i];
a[i]:=a[j];
a[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if pthen qs(p,j);
if ithen qs(i,q);
end;
procedure px;
var
i,j,t:dword;
begin
for i:=1 to 4 do
for j:=i+1 to 4 do
if q[i]>q[j] then begin t:=q[i]; q[i]:=q[j]; q[j]:=t; end;
end;
procedure update(x:tree);
begin
x^.sum:=x^.ls^.sum+x^.rs^.sum;
x^.maxl:=max(x^.ls^.maxl,x^.ls^.sum+x^.rs^.maxl);
x^.maxr:=max(x^.rs^.maxr,x^.rs^.sum+x^.ls^.maxr);
end;
procedure newx(x:tree;l,t:longint);
begin
x^.l:=l;
x^.r:=l;
x^.sum:=t;
x^.maxl:=t;
x^.maxr:=t;
x^.ls:=nil;
x^.rs:=nil;
end;
procedure build(x:tree;l,r:longint);
var
mid:longint;
begin
if l=r then
begin
newx(x,l,1);
exit;
end;
x^.l:=l;
x^.r:=r;
mid:=(l+r)div 2;
new(x^.ls);
build(x^.ls,l,mid);
new(x^.rs);
build(x^.rs,mid+1,r);
update(x);
end;
procedure rebuild(x,y:tree;v:longint);
var
mid:longint;
begin
if x^.l=x^.r then
begin
newx(y,x^.l,-1);
exit;
end;
y^:=x^;
mid:=(x^.l+x^.r)div 2;
if v<=mid then
begin
new(y^.ls);
rebuild(x^.ls,y^.ls,v);
end
else
begin
new(y^.rs);
rebuild(x^.rs,y^.rs,v);
end;
update(y);
end;
function getsum(x:tree;l,r:longint):longint;
var
mid:longint;
begin
if l>r then exit(0);
if (x^.l=l)and(x^.r=r) then exit(x^.sum);
mid:=(x^.l+x^.r)div 2;
if r<=mid then exit(getsum(x^.ls,l,r));
if l>mid then exit(getsum(x^.rs,l,r));
exit(getsum(x^.ls,l,mid)+getsum(x^.rs,mid+1,r));
end;
function getmaxl(x:tree;l,r:longint):longint;
var
mid:longint;
begin
if (x^.l=l)and(x^.r=r) then begin exit(x^.maxl); end;
mid:=(x^.l+x^.r)div 2;
if r<=mid then exit(getmaxl(x^.ls,l,r));
if l>mid then exit(getmaxl(x^.rs,l,r));
if (r>mid)and (l<=mid) then exit(max(getmaxl(x^.ls,l,mid),getsum(x^.ls,l,mid)+getmaxl(x^.rs,mid+1,r)));
end;
function getmaxr(x:tree;l,r:longint):longint;
var
mid:longint;
begin
if (x^.l=l)and(x^.r=r) then exit(x^.maxr);
mid:=(x^.l+x^.r)div 2;
if r<=mid then exit(getmaxr(x^.ls,l,r));
if l>mid then exit(getmaxr(x^.rs,l,r));
exit(max(getmaxr(x^.rs,mid+1,r),getsum(x^.rs,mid+1,r)+getmaxr(x^.ls,l,mid)));
end;
function cal(r:longint):longint;
begin
cal:=getsum(tr[vsn[r]],q[2]+1,q[3]-1)+getmaxl(tr[vsn[r]],q[3],q[4])+getmaxr(tr[vsn[r]],q[1],q[2]);
end;
function solve():longint;
var
le,ri,mid:longint;
begin
le:=1;
ri:=size+1;
while ledo
begin
mid:=(le+ri)div 2;
if cal(mid)<0 then ri:=mid
else le:=mid+1;
end;
exit(le-1);
end;
begin
readln(n);
for i:=1 to n do
begin
read(a[i].t);
a[i].id:=i;
end;
qs(1,n);
a[0].t:=0;
last:=a[1].t;
b[1]:=last;
a[1].t:=1;
for i:=2 to n do
if a[i].t=last then a[i].t:=a[i-1].t
else begin last:=a[i].t; a[i].t:=a[i-1].t+1; b[a[i].t]:=last; end;
size:=a[n].t;
new(tr[0]);
build(tr[0],1,n);
for i:=1 to n do
begin
if a[i].t>a[i-1].t then vsn[a[i].t]:=i-1;
new(tr[i]);
rebuild(tr[i-1],tr[i],a[i].id);
end;
readln(m);
last:=0;
for i:=1 to m do
begin
for j:=1 to 4 do
begin
read(q[j]);
q[j]:=(q[j]+last)mod n+1;
end;
px;
last:=b[solve()];
writeln(last);
end;
end.