zoukankan      html  css  js  c++  java
  • Codeforces 1446D2

    Codeforces 题面传送门 & 洛谷题面传送门

    人菜结论题做不动/kk

    首先考虑此题一个非常关键的结论:我们设整个数列的众数为 (G),那么在最优子段中,(G) 一定是该子段的众数之一。考虑反证法,如果最优子段中众数出现次数 (<) 该子段中出现次数最多的数的出现次数,那么我们考虑向左向右扩展这个区间,显然由于 (G) 是整个区间中出现次数最多的数,我们总可以找到一个时刻,满足 (G) 的出现次数 (ge) 原子段中出现次数最多的数的出现次数,此时子段的长度肯定不劣于原子段的长度,答案也不会变得更差。

    看出这个性质之后 D1 就变得异常 trivial 了,考虑枚举除了 (G) 之外字段中另一个众数 (x),那么考虑一个非常常用的套路:将序列中 (G) 的权值看作 (1)(x) 的权值看作 (-1),那么一个子段满足条件,当且仅当该子段中所有数的权值之和恰好为 (0),拿个桶记录一下即可。

    接下来考虑怎样解 D2。注意到这个东西长得像极了 P4062 Code+#1 Yazid 的新生舞会,而这东西用线段树显然是不太好维护的,因此考虑我的那个根分做法。考虑将所有数分为出现次数 (lesqrt{n})(>sqrt{n}) 进行处理。出现次数 (>sqrt{n}) 的数的个数显然是 (mathcal O(sqrt{n})) 级别的,我们对于这些数重复一遍 D1 的过程即可。对于出现次数 (lesqrt{n}) 的数我们换个角度批量处理这些数,即我们不关心出现次数最多的是哪个数,我们直接枚举众数的出现次数 (c),然后双针,对于每个左端点,向右一直扩展直到其中出现次数最多的数出现次数 (>c),如果我们发现出现次数最多的数不唯一则更新答案即可。这样复杂度就是 (nsqrt{n})

    const int MAXN=2e5;
    const int DLT=MAXN+3;
    int n,a[MAXN+5],cnt[MAXN+5],fst[DLT<<1],cnt_cnt[MAXN+5],res=0;
    int main(){
    	scanf("%d",&n);int G=0,mxcnt=0,lim=(int)sqrt(n),mx=0;
    	for(int i=1;i<=n;i++) scanf("%d",&a[i]),cnt[a[i]]++;
    	for(int i=1;i<=n;i++) chkmax(mx,cnt[i]);
    	for(int i=1;i<=n;i++) if(cnt[i]==mx) mxcnt++,G=i;
    	if(mxcnt>=2) return printf("%d
    ",n),0;
    //	printf("%d
    ",G);
    	for(int i=1;i<=n;i++) if(cnt[i]>lim&&i!=G){
    		memset(fst,-1,sizeof(fst));fst[DLT]=0;
    		for(int j=1,s=0;j<=n;j++){
    			if(a[j]==G) s++;if(a[j]==i) s--;
    			if(~fst[s+DLT]) chkmax(res,j-fst[s+DLT]);
    			else fst[s+DLT]=j;
    		}
    	} //printf("%d
    ",res);
    	for(int i=1;i<=lim+3;i++){
    		memset(cnt,0,sizeof(cnt));int mx=0;
    		memset(cnt_cnt,0,sizeof(cnt_cnt));
    		for(int l=1,r=1;l<=n;l++){
    			while(r<=n&&max(mx,cnt[a[r]]+1)<=i){
    				cnt_cnt[cnt[a[r]]]--;cnt[a[r]]++;cnt_cnt[cnt[a[r]]]++;
    				chkmax(mx,cnt[a[r]]);++r;
    			} //printf("%d %d %d
    ",i,l,r);
    			if(cnt_cnt[mx]>=2) chkmax(res,r-l);
    			cnt_cnt[cnt[a[l]]]--;cnt[a[l]]--;cnt_cnt[cnt[a[l]]]++;
    			if(!cnt_cnt[mx]) mx--;
    		}
    	} printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    iOS开发allocWithZone介绍
    如何快速的查看一段代码的执行时间
    iOS关于setContentOffset的一些细节问题
    iOS开发libz.dylib介绍
    C#窗体无法接受Keydown事件
    visual studio 2010 C#编程时 没有.NET framework 2.0目标框架的解决办法
    StringBuilder类与String类的区别
    Refresh和Invalidate的比较
    正则表达式
    Queue 先进先出队列的操作
  • 原文地址:https://www.cnblogs.com/ET2006/p/Codeforces-1446D2.html
Copyright © 2011-2022 走看看