0
点赞
收藏
分享

微信扫一扫

51nod算法训练


文章目录

  • ​​1096 距离之和最小​​
  • ​​1116 K进制下的大数​​
  • ​​2281 树的Size之和​​

1096 距离之和最小

#include<bits/stdc++.h>
using namespace std;
long long v[10005];

int main () {
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> v[i];
//sort(v + 1, v+n + 1);// 排序 1~n的位置
// 快速排序,归并排序。
long long t = (n + 1) / 2;
nth_element(v + 1, v + t, v + 1 + n);
long long sum = 0, k = v[t];
// 第1个参数表示起始位置,第3个参数表示终止位置,第2个参数,表示这个参数的位置就是排序好的数组
//该有的位置。但它不是排序
// 1 3 9 4 2
// sort(a, a + 1, a + n);//a是从0开始的数组
// 1 2 9 3 4
// string a = "9123456"; vector<int> b{1,5,2,3};
// sort(a.begin(), a.end());
// sort(b.begin(), b.end());
for (int i = 1; i <= n;i++) sum += abs(k - v[i]);
cout << sum << endl;
return 0;
}

使用long long ,并且很容易想到,中位数是距离最小的位置。可以推导出来。比如,如果枚举到某点,靠左,则右边的点Ri更多,那么,这个点越向左移动,总距离增加 ​​Li - Ri​​​,所以点只能向右移动。
同理,点靠右则只能向左移动。
所以,该点只能是中位数。

如何求中位数?sort()排序,那么中间那个数就是中位数。复杂度就是nlogn
或者使用algorithm中提供的另一个库函数。nth_element(),第1,3,参数标记其实和终止的位置,可以是迭代器。中间第2个参数k也是迭代器,那么。该函数执行完毕之后,也会令k位置的数,一定是排序后的数。也就是说,前面k - 1个数都小于等于a[k],后面n - k个数都大于等于a[k],但是这些数没有排序。具体用法在cppreference中。

1116 K进制下的大数

#include<bits/stdc++.h>
using namespace std;
long long v[10005];

int main () {
int n;
cin >> n;
for (int i = 1; i <= n; i++) cin >> v[i];
//sort(v + 1, v+n + 1);// 排序 1~n的位置
// 快速排序,归并排序。
long long t = (n + 1) / 2;
nth_element(v + 1, v + t, v + 1 + n);
long long sum = 0, k = v[t];
// 第1个参数表示起始位置,第3个参数表示终止位置,第2个参数,表示这个参数的位置就是排序好的数组
//该有的位置。但它不是排序
// 1 3 9 4 2
// sort(a, a + 1, a + n);//a是从0开始的数组
// 1 2 9 3 4
// string a = "9123456"; vector<int> b{1,5,2,3};
// sort(a.begin(), a.end());
// sort(b.begin(), b.end());
for (int i = 1; i <= n;i++) sum += abs(k - v[i]);
cout << sum << endl;
return 0;
}

这里要用到一个结论,如果一个数本身是k的倍数,那么这个数所有位上的和,也是k的倍数。具体推导可以在​​知乎​​​看到。
大概如下推导:比如abcd是3 的倍数。

一个整数如abcd
可以写成1000×a+100×b+10×c+d
=999×a+99×b+9×c+a+b+c+d

2281 树的Size之和

这道题如果使用​​vector<int> G[N]​​​这样的数据,会很简单,G[N]这个vector可以储存N这个节点的所有子节点。
本题解使用​​​链式前向星​​​去理解储存树。
不懂的去bilibili看​​​教程​​

//
// Created by YMXD on 2021/10/20.
//
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+50;
struct Edge{
int to,next;
};
int n, tot = 0, ans, head[maxn], cnt[maxn];
Edge edges[maxn<<1];
void add(int u,int v){
edges[tot].to=v;
edges[tot].next=head[u];//先初始化一个树,再把这个树放到链表前面
head[u]=tot++;
}
void dfs(int u,int fa,int d){
cnt[u] = 1;
for(int i=head[u];i!=-1;i=edges[i].next){
int v=edges[i].to;
if(v!=fa){
dfs(v,u,d+1);
cnt[u]+=cnt[v];
}
}
ans += cnt[u];
return;
}
int main(){
memset(head,-1,sizeof(head));
cin >> n;
for(int i=0;i<n-1;++i){
int u,v;
cin >> u >> v;
add(u,v);// u 和v相连
add(v,u);// v和u相连
}
dfs(1,0,1);// 1这个节点, 没有父节点所以填0, size是1.
cout << ans;
return 0;
}


举报

相关推荐

0 条评论