Description
1≤n,m≤50000
题解:
最简单的想法就是用莫队处理,然后加上线段树维护区间最大子段和,可是这样的时间复杂度是O(Nsqrt(n)logn),会达到10^8,这就非常不和谐了,那么我们怎么办呢?
对于维护区间最大子段和,我们可以考虑假如所有的操作都是插入操作,那么答案一定是不下降的,所以此时直接维护莫队的两个端点lr就可以了,问题是还有删除操作,那么又该怎么办呢?
我们可以把删除操作看作是还原插入操作,可是还是要打删除操作,但是我们可以转换一下处理方式。
每一次从b[i].l(r)扩展到b[i+1].l(r)(假设b[i].l>b[i+1].l)那么,我们可以把扩展前的值存储下来,然后扩展,扩展完后在暴力恢复,这样就可以保证不会出现删除操作了。
对于维护区间最大子段和,可以维护这个子段和的左右和中间端点,然后进行计算就可以了,细节比较多。
代码(长又丑)
uses math;
type node=record
l,r,id,bl:longint;
end;
var
i,j,n,m,size,now,l,r,cnt:longint;
a,ans,lp,rp:array[0..100000]of longint;
did:array[0..100000,0..3]of longint;
b:array[-1..100000]of node;
bo:array[0..100000]of boolean;
procedure qsort(l,r:longint);
var
i,j,m,m1:longint;
begin
i:=l;
j:=r;
m:=b[(l+r)div 2].bl;
m1:=b[(l+r)div 2].r;
repeat
while (b[i].bl<m)or((b[i].bl=m)and(b[i].r<m1))do inc(i);
while (b[j].bl>m)or((b[j].bl=m)and(b[j].r>m1))do dec(j);
if i<=j then
begin
b[-1]:=b[i];
b[i]:=b[j];
b[j]:=b[-1];
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure recover(u:longint);
var
i,j:longint;
x,y,z:longint;
begin
x:=did[u][2];
y:=did[u][0];
z:=did[u][1];
bo[x]:=false;
if (y<x)then
begin
rp[y]:=x-1;
lp[x-1]:=y;
end;
if (x<z)then
begin
rp[x+1]:=z;
lp[z]:=x+1;
end;
end;
procedure change(x,pd:longint);
var
delta,y:longint;
begin
if (l<=r)then
begin
delta:=0;
x:=a[x];
bo[x]:=true;
lp[x]:=x;
rp[x]:=x;
if (pd<>0)then
begin
inc(cnt);
did[cnt,0]:=x;
did[cnt,1]:=x;
did[cnt,2]:=x;
end;
if (x<>0)and(bo[x-1])then
begin
delta:=delta+x-lp[x-1];
lp[x]:=lp[x-1];
rp[lp[x-1]]:=x;
if pd=1 then
did[cnt,0]:=lp[x-1]
else did[cnt,0]:=0;
end;
if (x+1<=n)and(bo[x+1])then
begin
y:=lp[x];
delta:=delta+rp[x+1]-x;
rp[y]:=rp[x+1];
lp[rp[x+1]]:=y;
if pd=1 then
did[cnt][1]:=rp[x+1]
else did[cnt,1]:=0;
end;
now:=max(now,delta+1);
end;
end;
procedure solve;
var
i,j,k:longint;
tmp,tail:longint;
begin
for i:=1 to m do
begin
if (i=1)or(b[i].bl<>b[i-1].bl)then
begin
fillchar(bo,sizeof(bo),false);
tail:=min(b[i].bl*size,n)+1;
now:=0;
l:=tail;r:=0;
end;
while (r<b[i].r)do
begin
inc(r);
change(r,0);
end;
cnt:=0;
tmp:=now;
while (l>b[i].l)do
begin
dec(l);
change(l,1);
end;
ans[b[i].id]:=now;
now:=tmp;
l:=tail;
while cnt<>0 do
begin
recover(cnt);
dec(cnt);
end;
end;
end;
begin
readln(n,m);
for i:=1 to n do read(a[i]);
size:=trunc(sqrt(n))+1;
for i:=1 to m do
begin
read(b[i].l,b[i].r);
b[i].id:=i;
b[i].bl:=(b[i].l-1)div size+1;
end;
qsort(1,m);
solve;
for i:=1 to m do
begin
writeln(ans[i]);
end;
end.