CF1764C 题解

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;
	}
}
posted @ 2024-05-10 19:59  yhddd  阅读(7)  评论(0编辑  收藏  举报