【bzoj3585】mex 莫队+分块

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


你可能感兴趣的:(bzoj,莫队,分块)