CF1446D2 Frequency Problem (Hard Version)

CF1446D2 Frequency Problem (Hard Version)(根号分治)

首先这道题有一个结论:这两个元素当中一定有一个是众数,证明略。

那么考虑对于出现次数大于等于 \(\sqrt{n}\) 的数,我们可以把这些数枚举一下,然后这样做:

把值为当前数的位置标为 1 ,把值为众数的标为 -1 ,其他的都是 0 ,然后做一遍前缀和,记录每一个前缀和值的出现的最早的位置。

于是区间的长度那就是当前位置减掉这个前缀和第一次出现的位置(这样的话这个区间和就是 0)。

这部分的数的个数不超过 \(\sqrt{n}\) 个。

接下来是对于出现次数小于 $\sqrt{n} $的数。

我们可以枚举区间当中出现次数最多的数的次数,再枚举每一个 \(r\) ,求出最小的左端点 \(L_r\) ,整个过程是一个双指针。

可以参考这片题解

代码:

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;bool f=false;char ch=getchar();
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=2e5+5,T=505,INF=1e9+7;
int n,Maxn,cnt,Ans,S,val;
int a[N],Num[N],sum[N],t[N*2],cnt1[N],cnt2[N];
vector<int>v;
inline void Modify(int x,int v){cnt2[cnt1[x]]--,cnt1[x]+=v,cnt2[cnt1[x]]++;}
int main(){
	read(n),S=sqrt(n);
	for(int i=1;i<=n;i++) read(a[i]),Num[a[i]]++;
	for(int i=1;i<=n;i++){
		if(Num[i]==Maxn) cnt++;
		if(Num[i]>Maxn) cnt=1,Maxn=Num[i];
	}
	if(cnt>1){write(n);return 0;}
	for(int i=1;i<=n;i++){
		if(Num[i]==Maxn) val=i;
		else if(Num[i]>S) v.push_back(i);
	}
	for(int i=0;i<v.size();i++){
		int k=v[i];
		for(int j=1;j<=n;j++) sum[j]=sum[j-1]+(a[j]==k? -1:(a[j]==val? 1:0));
		for(int j=-n;j<=n;j++) t[n+j]=INF;
		for(int j=1;j<=n;j++) Ans=max(Ans,j-t[n+sum[j]]+1),t[n+sum[j-1]]=min(t[n+sum[j-1]],j);
	}
	for(int i=1;i<=S;i++){
		for(int j=1;j<=n;j++) cnt1[j]=cnt2[j]=0;
		int l=1,r=0;
		while(r<n){
			r++,Modify(a[r],1);
			while(cnt1[a[r]]>i) Modify(a[l],-1),l++;
			if(cnt2[i]>=2) Ans=max(Ans,r-l+1);
		}
	}
	write(Ans);
	return 0;
}
上一篇:poj2480 Longge‘s problem


下一篇:VMware安装centos7提示a problem has occured and the system can`t recover.