锰锌求救回滚莫队模板,WA28pts >__<
查看原帖
锰锌求救回滚莫队模板,WA28pts >__<
564732
TimSwn090306楼主2023/2/10 15:15

RT,

部分变量解释:

book[] 去重数组

siz 块长

bnum 块的数量

bfst[] 暴力求解中维护的第一次出现的位置

st[] lst[] 分别为维护出现第一次的位置和最后一次的位置

bl[] br[] 块的左右端点

bel[] 所属块的编号

con 贡献

rcon 右指针r产生的贡献

#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+1;
struct query{
	int l,r,id;
}q[maxn];
int n,m,ans[maxn],a[maxn],book[maxn];
int siz,bnum,bfst[maxn],st[maxn],lst[maxn],clr[maxn],bl[maxn],br[maxn],bel[maxn];
inline bool cmp(query x,query y){
	if (bel[x.l]!=bel[y.l]) return bel[x.l]<bel[y.l];
	return x.r<y.r;
}
inline int bf(int l,int r){
	int res=0;
	for (int i=l;i<=r;i++) bfst[a[i]]=0;
	for (int i=l;i<=r;i++){
		if (bfst[a[i]]) res=max(res,i-bfst[a[i]]);
		else bfst[a[i]]=i;
	}
	return res;
}
int main(){
	scanf("%d",&n);
	siz=sqrt(n);
	bnum=ceil((double)n/siz);
	for (int i=1;i<=bnum;i++){
		bl[i]=(i-1)*siz+1;
		br[i]=i*siz;
		for (int j=bl[i];j<=br[i];j++) bel[j]=i;
	}
	br[bnum]=n;
	for (int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		book[i]=a[i];
	}
	sort(book+1,book+n+1);
	int tot=unique(book+1,book+n+1)-book-1;
	for (int i=1;i<=n;i++) a[i]=lower_bound(book+1,book+tot+1,a[i])-book;
	scanf("%d",&m);
	for (int i=1;i<=m;i++){
		scanf("%d%d",&q[i].l,&q[i].r);
		q[i].id=i;
	}
	sort(q+1,q+m+1,cmp);
	for (int i=1,j=1;j<=bnum;j++){
		int l=br[j]+1,r=br[j],con=0,p=0;
		for (;bel[q[i].l]==j;i++){
			if (bel[q[i].r]==j){
				ans[q[i].id]=bf(q[i].l,q[i].r);
				continue;
			}
			while (r<q[i].r){
				r++;
				lst[a[r]]=r;
				if (!st[a[r]]){
					st[a[r]]=r;
					clr[++p]=a[r];
				}else con=max(con,r-st[a[r]]);
			}
			int rcon=con;
			while (l>q[i].l){
				l--;
				if (!lst[a[l]]) lst[a[l]]=l;
				else con=max(con,lst[a[l]]-l); 
			}
			ans[q[i].id]=con;
			while (l<=br[j]){
				if (lst[a[l]]==l) lst[a[l]]=0;
				l++;
			}
			con=rcon;
		}
		for (int k=1;k<=p;k++) lst[clr[k]]=st[clr[k]]=0; 
	}
	for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

九九九敏敏敏qwq

2023/2/10 15:15
加载中...