[BZOJ3339] Rmq Problem&&[BZOJ3585] mex

传送门

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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值