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;
}
哈哈哈虽然说好理解,但是自己肯定写不出哈哈哈,,,,