目录
改造二叉树
题目描述
在计算机科学中,二叉树是每个节点最多有两个子节点的有序树。通常子节点被称作“左孩子”
和“右孩子”。二叉树常被用作二叉搜索树和二叉堆。
我们现在讨论二叉搜索树。什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设 key[p]
表示节点 p 上的数值。对于其中的每个节点 p,若其存在左孩子 lch,则 key[p]>key[lch];若其存
在右孩子 rch,则 key[p]<key[rch]。注意,应该是所有的左子树中节点的 key 小于当前节点 key,
所有右子树中节点的 key 大于当前节点 key。
对于每个节点,无论如何改变其数值,费用总等于 1.
现在给定一棵二叉树,可以任意修改节点的数值,要求用最小的费用将其变成一棵二叉搜索树。
输入输出格式
输入:
第一行一个整数 N,表示二叉树中的节点数;
第二行 N 个整数,每两个整数之间用一个空格隔开,第 i 个整数 Ai表示第 i 个节点的原始数值;
再接下来第 3 行到第 N+1 行,每行两个整数 fa 和 x,中间用一个空格隔开,第 i+1 行表述的是节点
i 的父节点标号是 fa 及父子关系(x=0 表示节点 i 为节点 fa 的左孩子,x=1 表示节点 i 为节点 fa
的右孩子),标号为 1 的节点一定是二叉树的根。
输出:
输出共一行一个整数,即最小的费用值。
输入输出样例
样例输入:
3
2 2 2
1 0
1 1
样例输出:
2
解题思路
要从最下面开始修改,并不需要真正的去修改权值,因为这道题目权值不管怎么更改都是一样的代价
附上代码:
#include <iostream>
#include <cstdio>
const int MaxN = 1e5 + 5;
using namespace std;
struct tree{
int Ls,Rs,Data;
}Tree[MaxN];
int N;
int Total;
int Q[MaxN];
void Find(int x) {
int L = 1, R = Total;
while (L <= R) {
int Mid = (R - L >> 1) + L;
if (Q[Mid - 1] < x && x < Q[Mid]) {
Q[Mid] = x;
break ;
}
if (x > Q[Mid]) L = Mid + 1;
else R = Mid - 1;
}
}
void Dfs(int Root) {
if (Tree[Root].Ls) Dfs (Tree[Root].Ls);
if (Tree[Root].Data > Q[Total])Q[++ Total] = Tree[Root].Data;
else Find (Tree[Root].Data);
if (Tree[Root].Rs)Dfs(Tree[Root].Rs);
}
int main() {
scanf ("%d", &N);
for (int i = 1; i <= N; ++ i)scanf ("%d", &Tree[i].Data);
for (int i = 2, x, y; i <= N; ++ i) {
scanf ("%d %d", &x, &y);
if (y)Tree[x].Rs = i;
else Tree[x].Ls = i;
}
Q[Total] = -1;
Dfs(1);
printf ("%d\n", N - Total);
}
自己理解吧[doge]
回家
题目描述
有 N 头奶牛,Farmer John 想送每头奶牛回家,第 i 头奶牛被送回家的单程时间是 Ti(返回牛圈
的时间也同样为 Ti);如果第 i 头奶牛没有被送回家,那么它每一时刻的花费为 Di;当然被送的这
头奶牛是不会在有花费的;现在 Farmer John 想知道把这 N 头奶牛全部都送回家后,总共的最小花
费是多少。
输入输出格式
输入:
第一行一个整数 N,表示 Farmer John 有 N 头奶牛;
下面 N 行,每行 2 个整数 Ti,Di;
输出:
共一行一个整数,表示 Farmer John 把所有奶牛都送回家之后的最小花费;
输入输出样例
样例输入:
3
100 10
200 10
300 10
样例输出:
8000
解题思路
贪心的思路来排序,唉,没错!就硬贪!
附上代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
const int MaxN = 1e6 + 5;
using namespace std;
struct cow {
int CostTime;
int Second_Cost;
bool operator <(const cow &Y) const {//重载运算符来排序
return CostTime * Y.Second_Cost < Y.CostTime * Second_Cost;//没有错,就是这样的贪心思路!
}
}Cow[MaxN];
int N;
long long Num;
long long Ans;
int main() {
scanf ("%d", &N);
for (int i = 1; i <= N; ++ i)scanf ("%d %d", &Cow[i].CostTime, &Cow[i].Second_Cost), Num += Cow[i].Second_Cost;//定义Num方便后面计算
sort (Cow + 1, Cow + N + 1);
for (int i = 1; i <= N; ++ i) {
Num -= Cow[i].Second_Cost;//送走的这一只牛不会增加花费
Ans += Num * Cow[i].CostTime * 2;
}
printf ("%lld\n", Ans);
}
/*
3
100 10
200 10
300 10
*/
奶酪加工厂
题目描述
奶牛们收购了一个奶酪工厂。
接下来的 N 个星期里,牛奶价格和劳力价格不断起伏。第 i 周,生产一个单位奶酪需要 Ci 便
士。工厂有一个货栈,保存一个单位奶酪,每周需要 S 便士,这个费用不会变化,货栈十分强大,
可以存无限量的奶酪,而且保证它们不变质。
工厂接到订单,在第 i 周需要交付 Yi 单位的奶酪给委托人,第 i 周刚生产的奶酪,以及之前
的存货,都可以作为产品交付。
请帮奶牛们计算这段时间里完成任务的最小代价。
输入输出格式
输入:
第 1 行输入两个整数 N 和 S;
接下来 N 行,输入 Ci 和 Yi;
输出:
输出共一行一个整数,最少的代价;
输入输出样例
样例输入:
4 5
88 200
89 400
97 300
91 500
样例输出:
126900
解题思路
看看是在之前做好比较有还是现在做比较优
附上代码
#include <iostream>
#include <cstdio>
const int MaxN = 1e4 + 5;
using namespace std;
int N;
long long S;
long long C[MaxN],Y[MaxN];
long long Ans = 0;
int main() {
scanf ("%d %lld", &N, &S);
for (int i = 1; i <= N; ++ i) {
long long MinTotal = 0x7fffffff;
scanf ("%lld %lld", &C[i], &Y[i]);
for (int j = 1; j <= i; ++ j) {//比较懒就写成1~i了
MinTotal = min(MinTotal, Y[i] * C[j] + (i - j) * S * Y[i]);
}
Ans += MinTotal;
}
printf ("%lld\n", Ans);
}
同学会
题目描述
毕业 25 年以后,我们的主人公开始准备同学聚会。打了无数电话后他终于搞到了所有同学的
地址。他们有些人仍在本城市,但大多数人分散在其他的城市。不过,他发现一个巧合,所有地址
都恰好分散在一条铁路线上。他准备出发邀请但无法决定应该在哪个地方举行宴会。最后他决定选
择一个地点,使大家旅行的花费和最小。
不幸的是,我们的主人公既不擅长数学,也不擅长计算机。他请你帮忙写一个程序,根据他同
学的地址,选择聚会的最佳地点。
输入输出格式
输入:
输入文件的第一行为 N,表示城市个数。
以下 N 行,每一行描述了一个城市的信息。
首先是城市里同学的个数 M(M<1000),紧跟着是这个城市到 Moscow(起点站)的距离 L(L<10000)
(km),最后是城市的名称(0<字符串长度<255)。最后一行描述的总是 Moscow,它在铁路线的一端,
距离为 0。
输出:
聚会地点城市名称和旅行费用(单程),两者之间用一空格隔开。每 km 花费一个卢布。
输入输出样例
样例输入:
5
7 9289 Vladivostok
5 8523 Chabarovsk
3 5184 Irkutsk
8 2213 Yalutorovsk
10 0 Moscow
样例输出:
Yalutorovsk 112125
解题思路
因为数据很小,所以直接暴力枚举安排的地点,然后暴力求出费用最后打擂台
附上代码:
#include <iostream>
#include <cstdio>
#include <cmath>
const int MaxN = 155;
using namespace std;
struct Place {
string Name;
int Number;
int L;
}P[MaxN];
long long MinAns = 0x7fffffff;
string MinPlace;
int N;
int main() {
scanf ("%d", &N);
for (int i = 1; i <= N; ++ i) {
scanf ("%d %d", &P[i].Number, &P[i].L);
cin >> P[i].Name;
}
for (int i = 1; i <= N; ++ i) {//暴力枚举安排地点
long long Total = 0;
for (int j = 1; j <= N; ++ j) {
if (i == j)continue ;
Total += (abs (P[i].L - P[j].L) * P[j].Number);//暴力求费用
}
if (MinAns > Total) {//打擂台
MinAns = Total;
MinPlace = P[i].Name;
}
}
cout << MinPlace << ' ' << MinAns;//圆满输出
}