模拟题1(考虑周全以及情况较多)

牛客小白月赛96(重现赛)D题

题目解析以及注意事项

该题主要是找线路最多和最少的各种情况,从而达到整体连通图的构建代价最小的情况。
注意事项:a,b的正负影响着这个图的线尽可能的多还是少
思路图
{ a ≥ b { b < 0 a < 0 : 能连的线都连上 b < 0 a ≥ 0 :奇偶性不同线能连的的全连上 b > 0 :连奇偶性不同的点,而且线的数量要尽量小 a < b { a < 0 b < 0 : 能连的线都连上 a < 0 b ≥ 0 : 奇偶性相同的点互相之间能连的都连上,最后连一个奇偶性不同的点以形成连通图 a > 0 : 奇偶性相同的点互相之间连上,而且尽量少,最后连一个奇偶性不同的点 \begin{cases}a\geq b & \begin{cases}b<0 & a<0:能连的线都连上\\ b<0 & a\geq0:奇偶性不同线能连的的全连上\\ b>0 & :连奇偶性不同的点,而且线的数量要尽量小\end{cases}\\ a<b & \begin{cases}a<0 & b<0:能连的线都连上\\ a<0 & b\geq0:奇偶性相同的点互相之间能连的都连上,最后连一个奇偶性不同的点以形成连通图\\ a>0 & :奇偶性相同的点互相之间连上,而且尽量少,最后连一个奇偶性不同的点\end{cases}\end{cases} aba<b b<0b<0b>0a<0:能连的线都连上a0:奇偶性不同线能连的的全连上:连奇偶性不同的点,而且线的数量要尽量小 a<0a<0a>0b<0:能连的线都连上b0:奇偶性相同的点互相之间能连的都连上,最后连一个奇偶性不同的点以形成连通图:奇偶性相同的点互相之间连上,而且尽量少,最后连一个奇偶性不同的点
注意事项
当考虑n个点之间所有能连的都连上的时候,线的数量count为
n ∗ ( n − 1 ) 2 \frac{n*(n-1)}{2} 2n(n1)
注意n数据范围是
1 ≤ n ≤ 2 e 5 1\leq n\leq 2e^5 1n2e5
而count如果不开long long会超,(呜呜呜,因为这个又多WA了一发)
其他情况同理需要考虑,所以最好全开ll。

 #define ll=long long;

key代码实现

odd记录数组中奇数的个数,even记录数组中偶数的个数。

	if(odd==0||even==0){
		if(a>=0)
		cout<<(n-1)*a<<endl;
		else cout<<(odd*(odd-1)>>1)*a+(even*(even-1)>>1)*a<<endl;
		return;
	}
	
	if(b<=a){
		if(b>=0) cout<<(odd+even-1)*b<<endl;
		else if(a>=0) cout<<odd*even*b<<endl;
		else if(a<0) cout<<odd*even*b+(odd*(odd-1)>>1)*a+(even*(even-1)>>1)*a<<endl;
		return;
	}else {
		if(a>=0)
		cout<<(odd+even-2)*a+b<<endl;
		else if(b>=0) cout<<((odd*(odd-1)>>1)+(even*(even-1)>>1))*a+b<<endl;
		else cout<<((odd*(odd-1)>>1)+(even*(even-1)>>1))*a+b*odd*even<<endl;
	}

完整代码

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define For for (ll i = 1; i <= n; i++)
#define rFor for (ll i = n; i > 0; i--)
#define rep(i, sta, end) for (ll i = sta; i <= end; i++)
#define rrep(i, end, sta) for (ll i = end; i >= sta; i--)
#define ALL(x) for (auto item : x)



inline void solve() {
	ll n,a,b;cin>>n>>a>>b;
	ll odd=0,even=0;
	ll tmp;
	For {
		cin>>tmp;
		odd+=(tmp%2==1);
		even+=(tmp%2==0);
	}
	if(n==1){
		cout<<0<<endl;
		return;
	}
	if(odd==0||even==0){
		if(a>=0)
		cout<<(n-1)*a<<endl;
		else cout<<(odd*(odd-1)>>1)*a+(even*(even-1)>>1)*a<<endl;
		return;
	}
	
	if(b<=a){
		if(b>=0) cout<<(odd+even-1)*b<<endl;
		else if(a>=0) cout<<odd*even*b<<endl;
		else if(a<0) cout<<odd*even*b+(odd*(odd-1)>>1)*a+(even*(even-1)>>1)*a<<endl;
		return;
	}else {
		if(a>=0)
		cout<<(odd+even-2)*a+b<<endl;
		else if(b>=0) cout<<((odd*(odd-1)>>1)+(even*(even-1)>>1))*a+b<<endl;
		else cout<<((odd*(odd-1)>>1)+(even*(even-1)>>1))*a+b*odd*even<<endl;
	}
}



int	 main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	ll num = 1;
	cin >> num;
	while (num--) {
		//cout << "Main function execute properly before solve function " << endl;
		solve();
		//	cout << "Main function execute properly after solve function" << endl;
	}
	return 0;
}
  • 29
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值