欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

思路题--CF1082E Increasing Frequency

程序员文章站 2022-03-14 19:47:14
...

传送门

大意就是给你nn个数,你可以选择一段区间加上某个值(可正负),问操作完之后CC出现的次数最大是多少?

我觉得我的做法很巧妙!首先要知道一段区间加上某个值以后这个区间原来=C=C的数会变,而对CC的贡献一定都是一个数而且a[l]=a[r]=a[l]=a[r]=这个数(显然)

因为权值都比较小,然后记录mx[a[i]]mx[a[i]]表示某个权值对答案的最大贡献,还要一个sum[i]sum[i]表示1i1-iCC的个数(原来序列中)

显然mx[a[i]]=max{sum[i]+1mx[a[i]]+1mx[a[i]]=max\begin{cases}sum[i]+1\\mx[a[i]]+1\end{cases}

ans=max{mx[a[i]]+sum[n]sum[i]}ans=max\{mx[a[i]]+sum[n]-sum[i]\}

到此就结束了,是不是特别简单qwqqwq

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 500005
using namespace std;
int n,c,a[maxn],pre[maxn],mx[maxn],ans,sum[maxn];

inline int rd(){
	int x=0,f=1;char c=getchar();
	while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}
inline int max(int x,int y){return x>y?x:y;}

int main(){
	n=rd(); c=rd();
	for(int i=1;i<=n;i++){
		a[i]=rd();
		if(a[i]==c) sum[i]=1;
	}
	for(int i=1;i<=n;i++) sum[i]+=sum[i-1];
	ans=sum[n];
	for(int i=1;i<=n;i++){
		if(a[i]==c) continue;
		mx[a[i]]=max(sum[i]+1,mx[a[i]]+1);
		ans=max(ans,mx[a[i]]+sum[n]-sum[i]);
	}
	printf("%d\n",ans);
	return 0;
}
相关标签: 模拟