标签:Deletions le Almost 题解 maxn ans 序列 长度 DP
题目大意
给定一个长度为 \(n\) 的序列 \(a_1,a_2,\dots,a_n\),每次操作你可以选择相邻的两个不同的数字删去,然后剩下的部分连成一个序列。
现在求让这个序列所以值相等的前提下,序列的最长长度。
多组数据,数据组数 \(T\le 1000\)
\(1\le n\le 5000\),\(1\le a_i\le n\),\(\sum n\le 10^4\)
题目解析
考虑 DP,发现很不可做。
由于 \(n\le 5000\),所以区间 DP 貌似不可做,因为如果是区间 DP 肯定需要枚举断点,不可行。
所以考虑线性 DP,然后枚举转移点 \(O(n^2)\) 做。
由于需要让剩下的数字一样,所以设 \(f_i\) 为前面 \(i\) 个并且第 \(i\) 个一定需要选的答案。
现在问题到了如何判断是否能够转移,也就是判断一段是否能全部删除光。
不难发现结论:一段数组可以删光当且仅当这段数组长度为偶数并且众数的出现次数不超过数组长度一半。
证明是显然的。
有了这个结论,我们可以预处理所有的区间是否能够删除即可。
int n,w[maxn][maxn],f[maxn],a[maxn],t[maxn],ans;
void work(){
n=read(); int i,j,maxx=-1; for(i=1;i<=n;i++) a[i]=read();
for(i=1;i<=n;i++) for(j=1;j<=n;j++) w[i][j]=i>j;
for(i=1;i<=n;i++){
maxx=-1; for(j=1;j<=n;j++) t[j]=0;
for(j=i;j<=n;j++){
t[a[j]]++; maxx=mmax(maxx,t[a[j]]);
if(maxx<=((j-i+1)>>1)&&((j-i)&1)) w[i][j]=1;
}
}
f[1]=1; for(i=2;i<=n;i++) if(w[1][i-1]) f[i]=1; else f[i]=-INF;
for(i=1;i<=n;i++) for(j=i-1;j>=1;j-=2) if(a[i]==a[j]&&w[j+1][i-1]) f[i]=mmax(f[i],f[j]+1);
ans=0; for(i=1;i<=n;i++) if(w[i+1][n]||i+1>n) ans=mmax(ans,f[i]); print(ans),pc('\n'); return;
}
标签:Deletions,le,Almost,题解,maxn,ans,序列,长度,DP 来源: https://www.cnblogs.com/jiangtaizhe001/p/16526002.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。