CF1699D Almost Triple Deletions(众数)
I_am_Accepted · · 题解
结论题。
结论: 序列可以被删完当且仅当长度为偶数且众数出现次数不多于序列一半。
证明:(严谨的证明 CF 上有,这里就不放了。)
首先众数出现次数多于一半显然不行。
设众数为
反证法。假设
照这样说,那
矛盾,原命题成立。
于是就有了 DP 的想法:
设
考虑转移
其中
至此
//We'll be counting stars.
#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define fir first
#define sec second
#define mkp make_pair
#define pb emplace_back
#define For(i,j,k) for(int i=(j),i##_=(k);i<=i##_;i++)
#define Rof(i,j,k) for(int i=(j),i##_=(k);i>=i##_;i--)
#define ckmx(a,b) a=max(a,b)
#define ckmn(a,b) a=min(a,b)
#define Fi(s) freopen(s,"r",stdin)
#define Fo(s) freopen(s,"w",stdout)
#define Fre(s) Fi(s".in"),Fo(s".out")
#define debug cerr<<"Line#"<<__LINE__<<endl
#define ll long long
const ll mod=1;
inline ll pw(ll x,ll y){ll r=1;while(y){if(y&1)r=r*x%mod;x=x*x%mod;y>>=1;}return r;}
#define int long long
#define N 5003
int cnt[N],a[N],f[N],n;
inline bool equ(int x,int y){return x==0 || y==n+1 || a[x]==a[y];}
void work(){
cin>>n;
For(i,1,n) cin>>a[i];
fill(f,f+2+n,0);
int mx;
For(i,0,n){
if(i && !f[i]) continue;
fill(cnt+1,cnt+1+n,0);
mx=0;
For(j,i+1,n+1){
if(((j^i)&1) && mx*2<=j-i && equ(i,j)) ckmx(f[j],f[i]+1);
ckmx(mx,++cnt[a[j]]);
}
}
cout<<f[n+1]-1<<endl;
}
int32_t main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;cin>>T;
while(T--)work();
return 0;}