蓝桥杯第三天打卡

1、接上回的颜色平衡树问题,上一篇的代码是暴力解法,运行是部分超时的,但只要加两行就可以了。代码如下

#include<iostream>
#include<algorithm>
#include<unordered_map>

using namespace std;
const int N = 200010;
unordered_map<int, int>sum[N], cnt[N];  //cnt存储子节点的颜色(有sum[N]个节点颜色相同的是cnt[N]个
int col[N];     //颜色
vector<int>e[N];  //节点
int ans = 0;  //构成平衡树的节点个数
int n;

void dfs(int u)
{
	cnt[u][col[u]]=sum[u][1]+=1;  
	for (auto &k : e[u])
	{
		dfs(k);  
		if (cnt[u].size() < cnt[k].size())
			swap(cnt[u], cnt[k]), swap(sum[u], sum[k]);
		for (auto &it : cnt[k])
		{
			int x = it.first, y = it.second;
			
			if (cnt[u].count(x) && !--sum[u][cnt[u][x]])
				sum[u].erase(cnt[u][x]);
			sum[u][cnt[u][x] += y]++;
		}
	}
	ans += sum[u].size() == 1;
}

int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		int a;  
		cin >> col[i] >> a;
		e[a].push_back(i);
	}
	dfs(1);
	cout << ans;
	return 0;
}

我的进度实在是非常慢啊,非常慢啊。到这里首先得去了解一下 unordered_map的用法(可用kimi chat 帮忙喔),这里unordered_map<int,int> cnt[N],这个cnt数组有N个unordered_map类型的值,cnt[i][n]表示第i个节点的键的值,n代表这里的键,cnt[i][n]代表的就是这个键的值。

上图是十四届蓝桥杯的颜色平衡数问题,题目中描述的树。圆圈内是节点编码,旁边的黑色数字代表节点颜色。从第一个子节点开始,颜色相同的节点个数为1的有一种情况,即写为{1:1},往上归并,到编号为4的节点时,颜色相同的节点个数为2的有一种情况,为1的有一种情况,写为{2:1,1:1},依次类推。代码中cnt代表每种颜色有几个节点,sum即上面写的键对值,即颜色相同的节点个数为几的有几种情况。

for里做的主要操作就是,假设某个节点颜色是1,判断在子树中存在1这个颜色,并且只有一个节点是1这个颜色,并且只有一个节点是某种颜色的情况只有一个,即写成{1:1,...},那现在颜色是1的节点有两个了,就不存在{1:1}这种情况了,所以要先把这个键对删除。

最后如果sum里只有一个键对,那么它就是一个平衡树。

还有个啥启发式合并的解法,目前我实在弄不懂啊哈哈哈,,,,

2、买瓜问题,这个就分三种情况,买一个,买半个,不买,三个深度遍历。注意要用long long,返回是signed,应该是int被定义成long long,所以不能用int返回了。

#include <iostream>
#include<algorithm>
#define int long long
using namespace std;
int ans = 50;//最小劈瓜数
int a[50];//瓜
int sum[50];//瓜的质量
int n, m;

int min(int a,int b)
{
	return a > b ? b : a;
}
void dfs(int s, int i, int cnt)
{
	if (cnt >= ans) return;
	if (s == m) ans = min(ans, cnt);
	if (i >= n || s >= m || s + sum[i] < m) return;
	dfs(s + a[i], i + 1,  cnt); //买一个瓜
	dfs(s + a[i] / 2, i + 1, cnt + 1);//半个瓜
	dfs(s, i + 1, cnt);//不买
}
signed main()
{
	cin >> n >> m;
	m *= 2; //都*2防止劈成小数
	for (int i = 0; i < n; i++)
		cin >> a[i], a[i] *= 2;
	sort(a, a + n, greater<>()); //从大到小排序

	for (int i = n - 1; i >= 0; i--) //当前瓜到最后一个瓜的质量和
		sum[i] = sum[i + 1] + a[i];
	dfs(0, 0, 0);
	if (ans == 50)
		cout << -1;
	else
		cout << ans;
	return 0;
}

哈哈哈虽然说好理解,但是自己肯定写不出哈哈哈,,,,

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值