Codeforces Round#635 Div.2 解题

6 篇文章 0 订阅

比赛时出了 A~C然后直接睡觉了。。

A.给你a, b, c, d(非递减序列)四个数字,要求输出x, y, z,满足以下条件:
x属于[a, b], y属于[b, c], z属于[c, d]
以x, y, z为边长可以构成一个三角形
保证解总是存在

想法: 根据两边之和大于第三边瞎搞。。也容易想到去构造等腰等边等特殊三角形,比如 x = b, y = c, z = c, 等等。。如果这都满足不了。。那也就没有解了。。因为x + y已经最大而z已经最小了

#include <bits/stdc++.h>
using namespace std;
int a, b, c, d;
//认真思考,注意边界
int main()
{
	std::ios::sync_with_stdio(false);
	int T;
	cin >> T;
	while(T--)
	{
		cin >> a >> b >> c >> d;
		cout << b << ' ' << c << ' ' << c << endl;
	}
	return 0;
}

B.有一条恶龙有x点血,你可以使用n次第一种法术,效果是让它的血量变为(当前血量除以二并向下取整 + 10), m次第二种法术,效果是直接让它掉10点血,给出x, n, m, 问你有没有屠龙方法。。

想法:贪心, 显然我们更喜欢先用第一种法术不断减少恶龙的生命值(如果不能减少就算了),再一口气把第二种法术用完斩杀。。

#include <bits/stdc++.h>
using namespace std;
int x, n, m;
//认真思考,注意边界
int main()
{
	std::ios::sync_with_stdio(false);
	int T;
	cin >> T;
	while(T--)
	{
		cin >> x >> n >> m;
		while(x >= m * 10 and n)
		{
			x = x / 2 + 10 < x? x / 2 + 10 : x;
			n--;
		}
		if(x > m * 10) cout << "NO" << endl;
		else cout << "YES" << endl;
	}
	return 0;
}

C.有一个王国有n座城市,整个王国是一个树形结构,1号节点为其首都,所有的城市分为两类:旅游城市和工业城市,有一天每个工业城市都要派出一名使者到首都去,定义每个使者的快乐度是其在去首都的路上旅游城市的数目,现在要求你安排k座城市作为工业城市,求快乐度之和的最大值。

想法:题目很良心,给了样例解释,通过样例解释我们容易想到先把叶子节点变为工业城市,因为叶子节点的深度最深,到根节点路径最长。但如果叶子节点变完了,k还有剩,那么该变哪里?不妨将这个看成一个染色问题。
我们考虑染非叶子节点的贡献,显然当我们不得不染一个非叶子节点的时候,其底下的子节点应该都被染完了(不然你会发现染它底下的节点更好),而且,当你染了这个节点以后,答案会加上这个节点到首都的路径上旅游城市数,但同时,会让下面的每一个节点到首都的旅游城市数少1,总体就是少了下面的节点个数。。于是我们dfs一下统计深度的同时统计一下这个节点往下(不含它自己)有多少个节点,按照 深度-往下含有的子节点的个数 从大到小排序,取前k个,加到一起就是答案了。。

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
int n, k, vis[N], sz[N];
typedef long long ll;
struct node{
	int no, dep, sz;
};
vector<int> G[N];
vector<node> d;
//认真思考,注意边界
bool cmp(node x, node y)
{
	return x.dep - x.sz > y.dep - y.sz;
}

void dfs(int x, int dep)
{
	vis[x] = 1;
	sz[x] = 1;
	for(int i = 0; i < G[x].size(); i++)
	{
		int v = G[x][i];
		if(!vis[v])
		{
			dfs(v, dep + 1);
			sz[x] += sz[v];
		}
	}
	node n = {x, dep, sz[x] - 1};
	d.push_back(n); 
}
inline void add(int u, int v)
{
	G[u].push_back(v);
	G[v].push_back(u);
}
int main()
{
	std::ios::sync_with_stdio(false);
	cin >> n >> k;
	for(int i = 0; i < n - 1; i++)
	{
		int u, v;
		cin >> u >> v;
		add(u, v);
	}
	dfs(1, 0);
	ll ans = 0;
	sort(d.begin(), d.end(), cmp);
	for(int i = 0; i < d.size() and k; i++, k--)
	{
		ans += d[i].dep - d[i].sz;
	}
	cout << ans << endl;
	return 0;
}

D题待补充。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值