两题本质是一样,只不过3585要离散化
这种不修改,不强制的问题,显然先考虑离线算法
这道题的思路和bzoj1878非常像
考虑到如果只是求每个前缀的mex,我们是很容易扫一遍就得出来的
我们设为这个位置的mex
考虑从左往右依次删除当前数会对后面产生什么影响
我们设删除数a[i],a[i]下一个相同数的位置为next[a[i]]
显然对于[i+1,next[a[i]]-1]这些位置的mex可能有影响(如过没有next,就说明对后面所有位置都可能有影响);
凡是大于a[i]的一律都变成了a[i]
因此我们考虑对每个询问按左端点排序
然后从左往右依次删除a[i](按上述对后面位置进行修改)
不难发现,当某个询问左端点=当前位置i时(当然是先查询后删除了),这个询问的答案就是右端点上的mex,
显然修改操作我们可以用线段树来维护,这样就解决了这个问题

 const inf=;
var loc,ans,next,last,sg,p,q,c,a,b:array[..] of longint;
tree:array[..] of longint;
d:array[..] of longint;
v:array[..] of boolean;
i,n,m,j,t,k:longint; procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;
a:=b;
b:=c;
end; function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end; function find(x:longint):longint;
var l,r,m:longint;
begin
l:=;
r:=t;
while l<=r do
begin
m:=(l+r) shr ;
if d[m]=x then exit(m);
if d[m]>x then r:=m- else l:=m+;
end;
end; procedure sort1(l,r:longint);
var i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=p[(l+r) div ];
repeat
while p[i]<x do inc(i);
while x<p[j] do dec(j);
if not(i>j) then
begin
swap(p[i],p[j]);
swap(q[i],q[j]);
swap(c[i],c[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort1(l,j);
if i<r then sort1(i,r);
end; procedure sort2(l,r:longint);
var i,j,x,y: longint;
begin
i:=l;
j:=r;
x:=b[(l+r) div ];
repeat
while b[i]<x do inc(i);
while x<b[j] do dec(j);
if not(i>j) then
begin
swap(b[i],b[j]);
inc(i);
j:=j-;
end;
until i>j;
if l<j then sort2(l,j);
if i<r then sort2(i,r);
end; procedure build(i,l,r:longint);
var m:longint;
begin
if l=r then
tree[i]:=sg[l]
else begin
tree[i]:=inf;
m:=(l+r) shr ;
build(i*,l,m);
build(i*+,m+,r);
end;
end; procedure push(i:longint);
begin
tree[i*]:=min(tree[i*],tree[i]);
tree[i*+]:=min(tree[i*+],tree[i]);
tree[i]:=inf;
end; procedure work(i,l,r,x,y,z:longint);
var m:longint;
begin
if (x<=l) and (y>=r) then
tree[i]:=min(tree[i],z)
else begin
if tree[i]<>inf then push(i);
m:=(l+r) shr ;
if x<=m then work(i*,l,m,x,y,z);
if y>m then work(i*+,m+,r,x,y,z);
end;
end; function ask(i,l,r,x:longint):longint;
var m:longint;
begin
if l=r then exit(tree[i])
else begin
if tree[i]<>inf then push(i);
m:=(l+r) shr ;
if x<=m then exit(ask(i*,l,m,x))
else exit(ask(i*+,m+,r,x));
end;
end; begin
readln(n,m);
for i:= to n do
begin
read(a[i]);
b[i]:=a[i];
end;
sort2(,n);
if b[]<> then
begin
inc(t);
d[]:=;
end;
inc(t);
d[t]:=b[];
for i:= to n do
begin
if b[i]=b[i-] then continue;
if b[i]-b[i-]> then
begin
inc(t);
d[t]:=b[i-]+;
end;
inc(t);
d[t]:=b[i];
end;
inc(t);
d[t]:=b[n]+;
k:=;
for i:= to n do
begin
loc[i]:=find(a[i]);
v[loc[i]]:=true;
while v[k] do inc(k);
sg[i]:=k;
end;
fillchar(last,sizeof(last),);
fillchar(next,sizeof(next),);
for i:=n downto do
begin
next[i]:=last[loc[i]];
last[loc[i]]:=i;
end; build(,,n);
for i:= to m do
begin
readln(p[i],q[i]);
c[i]:=i;
end; sort1(,m);
j:=;
for i:= to n do
begin
while p[j]=i do
begin
ans[c[j]]:=ask(,,n,q[j]);
inc(j);
end;
if next[i]=- then next[i]:=n+;
work(,,n,i+,next[i]-,loc[i]);
end;
for i:= to m do
writeln(d[ans[i]]);
end.

最新文章

  1. Polynomial Library in OpenCascade
  2. 【转】 C++的精髓——虚函数
  3. paip.python php的未来预测以及它们的比较优缺点
  4. 用Task代替TheadPool
  5. linux 系统运维
  6. C语言中void*详解及应用
  7. js获取数组中的最大值最小值
  8. leetcode:Number of 1 Bits
  9. openflashchart + flex
  10. js自动判断浏览器类型跳转到手机版
  11. 排序算法简介及其C实现
  12. Loader之一:基本原理
  13. 【腾讯Bugly干货分享】iOS 中 HTTPS 证书验证浅析
  14. JAVA_SE基础——44.抽象类的练习
  15. 77. Combinations (Recursion)
  16. atitit. java跟php的比较..为什么大企业喜欢java 而不是php
  17. 【编程小题目7】求s=a+aa+aaa+aaaa+aa...a的值
  18. [postgresql]ROWS is not applicable when function does not return a set问题解决
  19. 洛谷 P3128 [USACO15DEC]最大流Max Flow-树上差分(点权/点覆盖)(模板题)
  20. iOS设计模式 —— KVC

热门文章

  1. IOS-CGAffineTransformMake 矩阵变换 的运算原理
  2. linux文件系统和mount(硬盘,win分区,光驱,U盘)
  3. Java实现对文件的上传下载操作
  4. ST3破解命令
  5. 苹果开发 笔记(80)升级IOS 9 和 XCode 7 引起的问题记录
  6. nim
  7. LA 6474 Drop Zone (最小割)
  8. ASP.Net数据导出Excel的几种方法
  9. meta标签常用属性整理
  10. 使用appium做自动化时如何切换activity