【题解】CF1764C Doremy's City Construction

题目传送门

思路

首先我们思考一个性质,由于不能有连续单调不升/不降的三个点连在一起,所以对于单个点来讲,显然要么只和比它大的连边(称为A类点),要么只和比它小的连边(称为B类点),要么只和与自己一样大的连边(称为C类点),要么不连边(称为D类点)

首先D类点肯定是极力避免的,其次C类点能且仅能连一条边(显然可知),所以我们要优先考虑A类点和B类点

我们先假设所有点都是A类点或者B类点,那么排序后显然A类点可以和权值比该点大的所有B类点连边,反之亦然

我们发现,如果A类点和B类点的数量已知,那么显然让A类点的权值尽可能小、B类点的权值尽可能大最优

这样,问题就变成了对转化后的数组找分界线的问题

根据简单的均值不等式,容易得出分界线落在 \(\lfloor\frac{n}{2}\rfloor\) 是最优的

然而,如果分界线左右的点的权值相等,显然会变成C类点,就不能这么计算答案了

所以,实际上我们要把权值相等的数缩为一个数,然后再寻找分界线

当然,由于排序复杂度就为 \(O(n\log n)\) 了,所以无需优化枚举复杂度,暴力找即可

不过,如果所有点的权值都相等,那么就要尽可能地增多C类点了,这时答案为 \(\lfloor\frac{n}{2}\rfloor\)

总复杂度为排序复杂度,可以通过此题

代码

//吾日九省吾身:
//输入多而不快读乎?
//题目标注而不freopen乎?
//乘除并列先乘后除乎?
//不手撕样例直接写代码乎?
//不仔细读题直接关页面乎?
//1e9而不开long long乎?
//Ctrl+V而不改名称乎?(papaw->papan IMPLIES tg1=->2=)
//相信评测神机乎?
//多测清空不彻底乎?
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<iomanip>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<algorithm>
#include<utility>
#include<deque>
#include<ctime>
#include<sstream>
#include<list>
#include<bitset>
using namespace std;
typedef long long ll;
const ll nanhenhenaaaaaaaaaaa(-1145141919810);
ll T,n,ans;
ll num[5000233];
ll stk[5000233],top,numeral;
ll sum;
int main(){
	cin>>T;
	while(T--){
		cin>>n;ans=n>>1;
		sum=0;
		for(ll i=1;i<=n;++i){
			cin>>num[i];
			stk[i]=0;
		}
		sort(num+1,num+n+1);
		numeral=nanhenhenaaaaaaaaaaa;
		top=0;
		for(ll i=1;i<=n;++i){
			if(numeral!=num[i]){
				numeral=num[i];
				stk[++top]++;
			}
			else stk[top]++;
		}
		for(ll i=0;i<=top;++i){
			sum+=stk[i];
			ans=max(ans,sum*(n-sum));
		}
		cout<<ans<<endl;
	}
	return 0;
}
posted @ 2022-12-11 17:00  Binaries  阅读(63)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end