粉碎题解
思路
出题人题解。首先思考一个结论,最优的粉碎方案一定是粉碎整个序列的一段前缀,欲证明该结论,只需考虑最后一次粉碎操作即可。如果一对能匹配上的牌分别出现在原序列的
令
考虑如何进行转移。
合并一下就是:
此时我们已经得到的
于是我们得到了
代码
#include <bits/stdc++.h>
using namespace std;
int a[500010],d[500010],p[500010],c[500010];
bool f[500010];
int main(){
int t,n,ans;
scanf("%d",&t);
while(t--){
scanf("%d",&n);ans=0;
memset(d,0,sizeof(d));
for(int i=1;i<=n;i++)
scanf("%d",a+i),p[i]=d[a[i]],d[a[i]]=i;
for(int i=1;i<=n;i++){
f[i]=(c[p[i]-1]<c[i-1]||!p[i]);
c[i]=c[i-1]+(int)f[p[i]];
if(f[p[i]])ans=i;
}
printf("%d\n",ans);
}
return 0;
}