【重点】Codeforces Round #364 (Div. 2)
2016-07-23 16:35
239 查看
唉,有一场很好加分的场没加多少
确实如出题人所说,用各个难度梯度的简单题出了,但是只能说自己太菜了。
前40min ABC 都过了,都是乱搞题
D 推公式 推了好久都是错的,可能是半夜脑子不好使,居然在第二天发现推的公式对了大半,最后输出结果产生了问题,也是醉了。
E 主要想讲一下E, 赛后看了看hx的代码,觉得好厉害啊。 按这种想法写出来的代码简单,但是我不知道证明这种想法的正确性,模模糊糊的感觉应该是对的
题意:
给你一棵树 包含n个点,然后给你 2*k 个点, 要你从这2k个点中 选出k对点,使得k对点 距离和 最大。
n<2*1e5 k<=n/2
然后我想了一下, 点边都是10W,不太可能直接跑出来。
想一下 在一棵树中,从2*k中选出k对,求出每一对u,v 之间的距离。那么u,v必然不能在同一棵子树中,因为 假如在另外一颗子树中选出x,y 这样的话dis(u,v)+dis(x,y) < dis(u,x)+dis(v,y) 或者 dis(u,y)+dis(v,x)
照这个想法,我们只要选出一个root 建树,然后我们保证 root 的每一子树的所有被标记的节点数目 都 <= k ,因为如果某个子树的标记节点数目>k,那么就肯定有点无法和其他子树节点匹配到。
但是我并不知道 这个root 是不是一定存在,讲道理是应该存在的。
然后建好树,我们就只需要跑出来每个标记节点到root的距离,相加就好
确实如出题人所说,用各个难度梯度的简单题出了,但是只能说自己太菜了。
前40min ABC 都过了,都是乱搞题
D 推公式 推了好久都是错的,可能是半夜脑子不好使,居然在第二天发现推的公式对了大半,最后输出结果产生了问题,也是醉了。
E 主要想讲一下E, 赛后看了看hx的代码,觉得好厉害啊。 按这种想法写出来的代码简单,但是我不知道证明这种想法的正确性,模模糊糊的感觉应该是对的
题意:
给你一棵树 包含n个点,然后给你 2*k 个点, 要你从这2k个点中 选出k对点,使得k对点 距离和 最大。
n<2*1e5 k<=n/2
然后我想了一下, 点边都是10W,不太可能直接跑出来。
想一下 在一棵树中,从2*k中选出k对,求出每一对u,v 之间的距离。那么u,v必然不能在同一棵子树中,因为 假如在另外一颗子树中选出x,y 这样的话dis(u,v)+dis(x,y) < dis(u,x)+dis(v,y) 或者 dis(u,y)+dis(v,x)
照这个想法,我们只要选出一个root 建树,然后我们保证 root 的每一子树的所有被标记的节点数目 都 <= k ,因为如果某个子树的标记节点数目>k,那么就肯定有点无法和其他子树节点匹配到。
但是我并不知道 这个root 是不是一定存在,讲道理是应该存在的。
然后建好树,我们就只需要跑出来每个标记节点到root的距离,相加就好
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<stdlib.h> #include<queue> #include<stack> #include<map> #include<vector> #define mem(a) memset(a,0,sizeof(a)) #define pfn printf("\n") #define ll __int64 #define pfd(a) printf("%d\n",a) #define pf2d(a,b) printf("%d %d\n",a,b) #define pf3d(a,b,c) printf("%d %d %d\n",a,b,c) #define pfs(a) printf("%s\n",a) #define sfd(a) scanf("%d",&a) #define sf2d(a,b) scanf("%d%d",&a,&b) #define sf3d(a,b,c) scanf("%d%d%d",&a,&b,&c) #define sfs(a) scanf("%s",a) #define sf scanf #define pf printf #define fr(i,n) for(int i=0;i<n;i++) const double PI = acos(-1.0); const double e = exp(1.0); template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; } template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; } template<class T> inline T Min(T a, T b) { return a < b ? a : b; } template<class T> inline T Max(T a, T b) { return a > b ? a : b; } bool cmpbig(int a,int b){return a>b;} bool cmpsmall(int a,int b){return a<b;} using namespace std; #define clean(a) memset(a, 0, sizeof(a)) const int maxn = 200100; int n, k, root, w[maxn], size[maxn]; ll len[maxn]; vector<int> g[maxn]; void dfs(int t, int fa){ size[t] = w[t]; bool flag = 1; for(int i=0;i<g[t].size();i++){ int v=g[t][i]; if(v != fa){ dfs(v, t); size[t] += size[v]; if(size[v] > k) flag = 0; } } if(2 * k - size[t] > k) flag = 0; if(flag) root = t; } int dir[maxn]; void DFS(int t, int fa){ for(int i=0;i<g[t].size();i++){ int v=g[t][i]; if(v != fa){ dir[v]=dir[t]+1; DFS(v, t); } } } int main(){ //freopen("1.txt","r",stdin); scanf("%d%d", &n, &k); for(int i = 1; i <= 2 * k; ++i){ int u; scanf("%d", &u); w[u]++; } for(int i = 1; i < n; ++i){ int u, v; scanf("%d%d", &u, &v); g[u].push_back(v), g[v].push_back(u); } dfs(1, 0); // printf("root=%d\n",root); dir[root]=0; DFS(root, 0); __int64 ans=0; for(int i=1;i<=n;i++) if(w[i]>0){ ans+=dir[i]; } printf("%I64d\n", ans); return 0; }
相关文章推荐
- 递归打印一个数所有加和的方式
- unix网络编程1 5.4问题
- 织梦DedeCMS文章列表页自动统计当前栏目文档总数的方法
- Spring SpringMVC Mybatis 整合
- HDU 2124Repair the Wall(贪心)
- 加载不同大小的图片消耗的内存大小
- 以jar包形式启动heritrix
- css3 动画
- ASI与AFN的区别
- 基于总变差模型的纹理图像中图像主结构的提取方法
- swift_类和结构体
- Spark中使用Java编程的常用方法
- POJ1995Raising Modulo Numbers
- 织梦DEDECMS教程:去除列表页文章标题加粗标签
- 说文解字(二)
- Intent
- JAVA学习总结二十七
- poj 3641 Pseudoprime numbers
- hdu1885Key Task (BFS+状态压缩)
- 织梦CMS5.7版自动给图片添加alt属性的方法