CF1764C 题解
思路
不存在点 \(u,v,w\),满足 \(a_u\leq a_v\leq a_w\),且边 \((u,v),(v,w)\) 存在。
考虑先排序。
排序后,如果 \(a_i\) 连向 \(a_j(i\le j)\),那么 \(a_j\) 不能连向从 \(a_{j+1}\) 到 \(a_n\),但可以连向从 \(a_1\) 到 \(a_{i-1}\)。同时 \(a_i\) 不能连向从 \(a_1\) 到 \(a_{i-1}\),但可以从 \(a_{j+1}\) 连到 \(a_n\)。为了最大化连边,如果 \(a_i\) 连向 \(a_j\),则从 \(a_1\) 到 \(a_i\) 中每个点都会连边到从 \(a_j\) 到 \(a_n\) 的点。
所以在排序后的数组上找到 \(i\),满足 \(a_i\neq a_{i+1}\),最大化 \(i\times (n-i)\)。
但是,对于样例 \(4\),答案来自同一个数值间的连边。这种情况下,一个数与相等的数间不能有两条连边,注意提面中是 \(\leq\)。答案再与每种元素个数的一半取最大值。
多测清空。
code
int T;
int n,ans,a[maxn],z,p,q,t[maxn],cnt;
signed main(){
T=read();
while(T--){
n=read();
for(int i=1;i<=n;i++)a[i]=read();
sort(a+1,a+n+1);
cnt=0;
memset(t,0,sizeof(t));
for(int i=1;i<=n;i++){
if(a[i-1]!=a[i])++cnt;
t[cnt]++;
ans=max(ans,t[cnt]/2);
// cout<<ans<<" "<<t[cnt]<<" "<<cnt<<endl;
}
// cout<<ans<<" "<<cnt<<endl;
p=0;q=n;
for(int i=1;i<=cnt;i++){
// cout<<t[i]<<" ";
p+=t[i];q-=t[i];
ans=max(ans,p*q);
}
printf("%lld\n",ans);
ans=0;
}
}