AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3585
【题解】
这题思维上有些难度,蒟蒻不得不偷窥了popoQQQ大爷题解。
将1~n之间的自然数分成根号n块,每个块记录当前块中已经出现的不同的自然数的个数。
那么在查询时只需要检验每个块是否满足r[i]-l[i]+1==blo[i],找到第一个不满足以上条件的,然后在该块内暴力查找即可。
/*************
bzoj 3585
by chty
2016.11.29
*************/
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define FILE "read"
#define MAXN 200010
#define up(i,j,n) for(int i=j;i<=n;i++)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
struct node{int x,y,id;}q[MAXN];
int n,m,block,a[MAXN],ans[MAXN],vis[MAXN],blo[MAXN],l[MAXN],r[MAXN],belong[MAXN];
bool cmp(node a,node b) {return a.x/block==b.x/block?a.yn) return;
if(!vis[x]) blo[belong[x]]++;
vis[x]+=v;
if(!vis[x]) blo[belong[x]]--;
}
int query(){
if(!vis[0]) return 0;
int i;
for(i=1;l[i];i++) if(r[i]-l[i]+1!=blo[i]) break;
int temp=i;
up(i,l[temp],r[temp]) if(!vis[i]) return i;
return n;
}
void init(){
n=read(); m=read(); block=(int)sqrt(n*1.0);
up(i,1,n) a[i]=read();
up(i,1,m) q[i].x=read(),q[i].y=read(),q[i].id=i;
for(int i=1;(i-1)*block+1<=n;i++) l[i]=(i-1)*block+1,r[i]=min(i*block,n);
up(i,1,n) belong[i]=(i-1)/block+1;
}
void solve(){
sort(q+1,q+m+1,cmp);
int l(1),r(0);
up(i,1,m){
while(q[i].y>r) updata(a[++r],1);
while(q[i].yl) updata(a[l++],-1);
while(q[i].x