对于快排的深刻理解(双关键词)
然后分块 块长 (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.