题:https://codeforces.com/contest/1082/problem/E
题意:给出n个数和一个数c,只能操作一次将[L,R]之间的数+任意数,问最后该序列中能存在最多多少个c
分析:考虑dp,dp[i]表示将该位置染成c的答案,那么将该颜色染成c肯定要和其他和这个位置值相同的位置尝试染一染,这个尝试就是dp的取max值,这里采用的是遍历到某一个值就查询之前出现的最近的位置,然后尝试,因为往后递推这样的关系就会被连起来,接着就是预处理一下前后缀c的个数。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int M=5e5+5; int pre[M],suf[M],dp[M],a[M],las[M]; int main(){ int n,c; scanf("%d%d",&n,&c); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); pre[i]=pre[i-1]; if(a[i]==c) pre[i]++; } for(int i=n;i>=1;i--){ suf[i]=suf[i+1]; if(a[i]==c) suf[i]++; } int ans=0; for(int i=1;i<=n;i++){ dp[i]=pre[i-1]+1; if(las[a[i]]) dp[i]=max(dp[i],dp[las[a[i]]]+1); ans=max(ans,dp[i]+suf[i+1]); las[a[i]]=i; } printf("%d ",ans); }