http://www.lydsy.com/JudgeOnline/problem.php?id=3339
http://www.lydsy.com/JudgeOnline/problem.php?id=3585
有一个长度为n的数组{a1,a2,…,an}。m次询问,每次询问一个区间内最小没有出现过的自然数。
我们考虑离线处理
对于[1,R]的答案我们可以扫一遍O(N)时间处理出来
一个数一旦出现那么任意包含它的区间的答案就不是他了,也就是说对于第i位的数字,它的贡献(其实是否定答案的贡献)区间为[i,next[i]-1]
对于[L,R]到[L+1,R],第L位被扔出区间后,[L,next[L]-1]的答案就可以是x[L]了,用线段树标记比较一下就可以了
BZOJ 3585 需要先离散化求出next[i]
const
maxn=200005;
var
w:array[0..4*maxn,1..4]of longint;
next,y,z,t,ans:array[0..maxn]of longint;
x:array[0..maxn,1..3]of longint;
i,j,k:longint;
n,m:longint;
procedure sort(l,r:longint);
var i,j,a,b:longint;
begin
i:=l; j:=r; a:=x[(l+r) div 2,1];
repeat
while x[i,1]<a do inc(i);
while a<x[j,1] do dec(j);
if not(i>j) then
begin
b:=x[i,1]; x[i,1]:=x[j,1]; x[j,1]:=b;
b:=x[i,2]; x[i,2]:=x[j,2]; x[j,2]:=b;
b:=x[i,3]; x[i,3]:=x[j,3]; x[j,3]:=b;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r; w[a,3]:=0; w[a,4]:=-1;
if l=r then begin w[a,3]:=t[l]; exit; end;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure pushdown(a:longint);
begin
w[a,3]:=min(w[a,3],w[a,4]);
if w[a,1]=w[a,2] then begin w[a,4]:=-1; exit; end;
if w[a<<1,4]=-1 then w[a<<1,4]:=w[a,4] else w[a<<1,4]:=min(w[a,4],w[a<<1,4]);
if w[a<<1+1,4]=-1 then w[a<<1+1,4]:=w[a,4] else w[a<<1+1,4]:=min(w[a,4],w[a<<1+1,4]);
end;
procedure update(a,l,r,c:longint);
var mid:longint;
begin
if (w[a,1]=l)and(w[a,2]=r) then begin
if w[a,4]=-1 then w[a,4]:=c else w[a,4]:=min(w[a,4],c);
exit;
end;
if w[a,4]<>-1 then pushdown(a);
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then update(a<<1,l,r,c) else
if l>mid then update(a<<1+1,l,r,c)
else begin update(a<<1,l,mid,c); update(a<<1+1,mid+1,r,c); end;
end;
function query(a,l:longint):longint;
var mid:longint;
begin
if w[a,4]<>-1 then pushdown(a);
if w[a,1]=w[a,2] then exit(w[a,3]);
mid:=(w[a,1]+w[a,2])>>1;
if l<=mid then exit(query(a<<1,l)) else exit(query(a<<1+1,l));
end;
begin
readln(n,m);
for i:=1 to n do
begin
read(y[i]);
next[z[y[i]]]:=i;
z[y[i]]:=i;
end;
fillchar(z,sizeof(z),0); t[0]:=0;
for i:=1 to n do
begin
z[y[i]]:=1;
for j:=t[i-1] to maxn do
if z[j]=0 then begin t[i]:=j; break; end;
end;
build(1,1,n);
for i:=1 to m do
begin
readln(x[i,1],x[i,2]);
x[i,3]:=i;
end;
sort(1,m); {x[i,1],x[i,2]} x[0,1]:=1;
for i:=1 to m do
begin
if (x[i,1]<>x[i-1,1])then begin
for j:=x[i-1,1] to x[i,1]-1 do
if next[j]<>0
then update(1,j,next[j]-1,y[j])
else update(1,j,n,y[j]);
end;
ans[x[i,3]]:=query(1,x[i,2]);
end;
for i:=1 to m do
writeln(ans[i]);
end.
离散化 //慢的一逼T_T
const
maxn=400005;
var
w:array[0..4*maxn,1..4]of longint;
next,y,z,t,ans,g:array[0..maxn]of longint;
x:array[0..maxn,1..3]of longint;
i,j,k:longint;
n,m,len:longint;
procedure sort(l,r:longint);
var i,j,a,b:longint;
begin
i:=l; j:=r; a:=x[(l+r) div 2,1];
repeat
while x[i,1]<a do inc(i);
while a<x[j,1] do dec(j);
if not(i>j) then
begin
b:=x[i,1]; x[i,1]:=x[j,1]; x[j,1]:=b;
b:=x[i,2]; x[i,2]:=x[j,2]; x[j,2]:=b;
b:=x[i,3]; x[i,3]:=x[j,3]; x[j,3]:=b;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r; w[a,3]:=0; w[a,4]:=-1;
if l=r then begin w[a,3]:=t[l]; exit; end;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure pushdown(a:longint);
begin
w[a,3]:=min(w[a,3],w[a,4]);
if w[a,1]=w[a,2] then begin w[a,4]:=-1; exit; end;
if w[a<<1,4]=-1 then w[a<<1,4]:=w[a,4] else w[a<<1,4]:=min(w[a,4],w[a<<1,4]);
if w[a<<1+1,4]=-1 then w[a<<1+1,4]:=w[a,4] else w[a<<1+1,4]:=min(w[a,4],w[a<<1+1,4]);
end;
procedure update(a,l,r,c:longint);
var mid:longint;
begin
if (w[a,1]=l)and(w[a,2]=r) then begin
if w[a,4]=-1 then w[a,4]:=c else w[a,4]:=min(w[a,4],c);
exit;
end;
if w[a,4]<>-1 then pushdown(a);
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then update(a<<1,l,r,c) else
if l>mid then update(a<<1+1,l,r,c)
else begin update(a<<1,l,mid,c); update(a<<1+1,mid+1,r,c); end;
end;
function query(a,l:longint):longint;
var mid:longint;
begin
if w[a,4]<>-1 then pushdown(a);
if w[a,1]=w[a,2] then exit(w[a,3]);
mid:=(w[a,1]+w[a,2])>>1;
if l<=mid then exit(query(a<<1,l)) else exit(query(a<<1+1,l));
end;
begin
readln(n,m);
for i:=1 to n do
begin read(y[i]); x[i,1]:=y[i]; x[i,2]:=i; end;
sort(1,n);
len:=0; x[0,1]:=-1;
for i:=1 to n do
if x[i,1]<>x[i-1,1]
then begin inc(len); g[x[i,2]]:=len; end
else g[x[i,2]]:=len;
for i:=1 to n do
begin
next[z[g[i]]]:=i;
z[g[i]]:=i;
end;
fillchar(z,sizeof(z),0); t[0]:=0;
for i:=1 to n do
begin
if y[i]<=maxn then z[y[i]]:=1;
for j:=t[i-1] to maxn do
if z[j]=0 then begin t[i]:=j; break; end;
end;
build(1,1,n);
for i:=1 to m do
begin
readln(x[i,1],x[i,2]);
x[i,3]:=i;
end;
sort(1,m); {x[i,1],x[i,2]} x[0,1]:=1;
for i:=1 to m do
begin
if (x[i,1]<>x[i-1,1])then begin
for j:=x[i-1,1] to x[i,1]-1 do
if next[j]<>0
then update(1,j,next[j]-1,y[j])
else update(1,j,n,y[j]);
end;
ans[x[i,3]]:=query(1,x[i,2]);
end;
for i:=1 to m do
writeln(ans[i]);
end.