对于快排的深刻理解(双关键词)
然后分块 块长 (500000)^(1/3)=80 o((n/k)^2)+n log n+n*k) 理论上最快 实际 4.8s
更新块间答案(只与下标和数据是否相等有关)
之后查询 块间与暴力相结合
var i,j,k,l,m,n,q,w,x,y:longint;
a,b,next,c,t:array[0..500000] of longint;
f:array[0..6300,0..6300] of longint;
function jh(p,o:longint):boolean;
begin
if a[p]=a[o] then exit(p<o); exit(a[p]<a[o]);
end;
function min(p,o:longint):longint;
begin if p>o then exit(o);exit(p);end;
procedure sort(l,r: longint);
var i,j,x,y: longint;
begin
i:=l; j:=r; x:=b[(l+r)div 2];
repeat
while jh(b[i],x) do inc(i);
while jh(x,b[j]) do dec(j);
if i<=j then
begin
y:=b[i]; b[i]:=b[j]; b[j]:=y;
inc(i); j:=j-1;
end;
until i>=j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
begin
readln(n,m); k:=80;l:=n div k+1;
for i:=1 to n do begin read(a[i]); b[i]:=i; end;
readln; sort(1,n);
for i:=1 to n-1 do if a[b[i]]=a[b[i+1]] then next[b[i]]:=b[i+1];
for i:=1 to n do if (next[i]<>0) then c[i]:=next[i]-i;
for i:=1 to n do t[i]:=(i-1) div k+1;
fillchar(f,sizeof(f),$7f);
for i:=1 to n do if next[i]<>0 then
f[t[i],t[next[i]]]:=min(c[i],f[t[i],t[next[i]]]);
for i:=1 to l do for j:=i+1 to l do begin
f[i,j]:=min(f[i,j-1],f[i,j]); f[i,j]:=min(f[j,j],f[i,j]);end;
for i:=1 to m do begin
readln(x,y);
x:=x xor q; y:=y xor q;
if t[y]-t[x]<2 then begin q:=maxlongint;
for j:=x to y do if (0<next[j])and(next[j]<=y) then q:=min(q,c[j]);
if q>n then q:=-1; writeln(q);
end
else begin
q:=f[t[x]+1,t[y]-1];
for j:=x to t[x]*k do
if(0<next[j])and(next[j]<=y)then q:=min(q,c[j]);
for j:=(t[y]-1)*k to y do
if(0<next[j])and(next[j]<=y)then q:=min(q,c[j]);
if q>n then q:=-1; writeln(q);
end;
end;
end.