AGC007E Shik and Travel

题目大意:\(n\) 个点的二叉树,每个点要么两个儿子,要么没有儿子,每条边有边权。

你从 \(1\) 号节点出发,走到一个叶子节点。然后每一天,你可以从当前点走到另一个叶子。最后回到 \(1\) 号节点,要求到过所有叶子并且每条边经过恰好两次。求一种遍历顺序,使得每相邻两叶子间的边权和的最大值最小。

题解

考虑二分最大值,看是否可行。这个点是一种类似等号转限制的做法。

因此我们只需考虑能否在不经过权值和大于 \(k\) 的叶子间的路径即可。这个怎么做呢?由于我们只关心距离,我们对于每个点可以得到一些数对 \((a,b)\) ,表示当前点子树中可以从距离当前点距离为 \(a\) 的叶子进入,从距离当前点距离为 \(b\) 的叶子退出。并且记 \(S_u\) 为对于 \(u\) 这个点来说形如 \((a,b)\) 的数对集合。

对于没有儿子的点,存在数对 \((0,0)\) 。而对于有儿子的点,由题目限制每条边和每个叶子恰好过两次,可知一个子树内的叶子肯定先互相到达,再离开当前子树,去与最近的子树中的叶子互达。因此我们得到一个非叶子节点的数对,等价于我们将其左右子树的某两个叶子相连接,用左右子树的数对表示,可以得到对于一个子树的数对 \((a,b)\) 和另一个子树的数对 \((c,d)\) ,当 \(b+c+val[u][0]+val[u][1]\le k\) 时(\(val[u][0/1]\) 表示 \(u\) 向左右儿子的边权),这两个数对可以合并,得到数对 \((a+val[u][0],b+val[u][1])\) ,这是默认 \((a,b)\) 为左子树数对,反过来的话 \(val\) 换一下就好。

但是直接暴力合并数对是寄的。我们考虑优化,显然对于两个点对 \((a,b)\) 和 \((c,d)\) ,如果 \(a\le c,b\le d\) ,那么可以知道 \((c,d)\) 是无用的。其次由于我们希望合并出来的数对的两个值都尽量小,且每个数对 \((a,b)\) 都满足 \(a+b\le k\) ,我们对于一个子树中的数对肯定有唯一的一个另一个子树的数对与之对应来得到最小的数对。

我们对于数对按照 \(a\) 从小到大排序,那么由于 \(a+b\le k\) 显然 \(b\) 递减,我们考虑决策单调性来合并即可。

然后我们有决策单调性的话,显然复杂度就是数对总数的,然后由于是一个二叉树,易证复杂度 \(O(n\log n)\) ,总复杂度 \(O(34n\log n)\)。(\(34\) 是二分复杂度)

参考代码:

#include<bits/stdc++.h>
#define ll long long
#define db double
#define filein(a) freopen(#a".in","r",stdin)
#define fileot(a) freopen(#a".out","w",stdout)
#define sky fflush(stdout);
#define gc getchar
#define pc putchar
namespace IO{
inline bool blank(const char &c){
return c==' ' or c=='\n' or c=='\t' or c=='\r' or c==EOF;
}
inline void gs(char *s){
char ch=gc();
while(blank(ch) ) {ch=gc();}
while(!blank(ch) ) {*s++=ch;ch=gc();}
*s=0;
}
inline void gs(std::string &s){
char ch=gc();s+='#';
while(blank(ch) ) {ch=gc();}
while(!blank(ch) ) {s+=ch;ch=gc();}
}
inline void ps(char *s){
while(*s!=0) pc(*s++);
}
inline void ps(const std::string &s){
for(auto it:s)
if(it!='#') pc(it);
}
template<class T>
inline void read(T &s){
s=0;char ch=gc();bool f=0;
while(ch<'0'||'9'<ch) {if(ch=='-') f=1;ch=gc();}
while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=gc();}
if(ch=='.'){
db p=0.1;ch=gc();
while('0'<=ch&&ch<='9') {s=s+p*(ch^48);p*=0.1;ch=gc();}
}
s=f?-s:s;
}
template<class T,class ...A>
inline void read(T &s,A &...a){
read(s);read(a...);
}
};
using IO::read;
using IO::gs;
using IO::ps;
const int N=(1<<17)+3;
int n;
int ch[N][2],val[N][2];
struct node{
int a,b;
};
std::vector<node>S[N],psc;
void dfs(int u,ll k){
S[u].clear();
if(!ch[u][0]){
S[u].push_back({0,0});
return;
}
dfs(ch[u][0],k);
dfs(ch[u][1],k);
int lc=ch[u][0],rc=ch[u][1];
psc.clear();
int j=-1;
for(auto it:S[lc]){
while(j+1<S[rc].size() and S[rc][j+1].a+it.b+val[u][1]+val[u][0]<=k){
++j;
}
if(j>=S[rc].size() ) continue;
if(S[rc][j].a+it.b+val[u][1]+val[u][0]>k) continue;
psc.push_back({it.a+val[u][0],S[rc][j].b+val[u][1]});
}
j=-1;
for(auto it:S[rc]){
while(j+1<S[lc].size() and S[lc][j+1].a+it.b+val[u][1]+val[u][0]<=k){
++j;
}
if(j>=S[lc].size() ) continue;
if(S[lc][j].a+it.b+val[u][1]+val[u][0]>k) continue;
psc.push_back({it.a+val[u][1],S[lc][j].b+val[u][0]});
}
int sz=psc.size();
std::sort(psc.begin(),psc.end(),[](node x,node y){
return x.a<y.a;
});
for(int i=0;i<sz;++i){
if(i!=0){
if(psc[i-1].b<=psc[i].b){
continue;
}
}
S[u].push_back(psc[i]);
}
}
inline bool check(int u,ll k){
dfs(1,k);
return S[1].size();
}
int main(){
filein(a);fileot(a);
read(n);
for(int u=2;u<=n;++u){
int f,w; read(f,w);
if(!ch[f][0]) ch[f][0]=u,val[f][0]=w;
else ch[f][1]=u,val[f][1]=w;
}
ll l=0,r=1ll*(1ll<<17)*(1ll<<17),hf=r;
while(l<=r){
ll mid=(l+r)>>1;
if(check(1,mid) ){
r=mid-1;hf=mid;
}else{
l=mid+1;
}
}
printf("%lld\n",hf);
return 0;
}

AGC007E Shik and Travel 解题报告的更多相关文章

  1. [JZOJ 5911] [NOIP2018模拟10.18] Travel 解题报告 (期望+树形DP)

    题目链接: http://172.16.0.132/senior/#contest/show/2530/1 题目: EZ同学家里非常富有,但又极其的谦虚,说话又好听,是个不可多得的人才.        ...

  2. codeforces 466A. Cheap Travel 解题报告

    题目链接:http://codeforces.com/problemset/problem/466/A 题目意思:一个 ride 需要 a 卢布,m 个 ride 需要 b 卢布,这两种方案都可以无限 ...

  3. [jzoj 5177] [NOIP2017提高组模拟6.28] TRAVEL 解题报告 (二分)

    题目链接: https://jzoj.net/senior/#main/show/5177 题目: 题解: 首先选出的泡泡怪一定是连续的一段 L,R 然后 L 一定属于虫洞左边界中的某一个 R 也同样 ...

  4. [AGC007E] Shik and Travel

    题目 给定一棵n节点的 以1为根的 满二叉树 (每个非叶子节点恰好有两个儿子)n−1 条边. 第ii条边连接 i+1号点 和 ai, 经过代价为vi设这棵树有m个叶子节点定义一次合法的旅行为:(1) ...

  5. AtCoder AGC007E Shik and Travel (二分、DP、启发式合并)

    题目链接 https://atcoder.jp/contests/agc007/tasks/agc007_e 题解 首先有个很朴素的想法是,二分答案\(mid\)后使用可行性DP, 设\(dp[u][ ...

  6. 【LeetCode】Gas Station 解题报告

    [LeetCode]Gas Station 解题报告 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problems/gas-station/#/descr ...

  7. 【LeetCode】743. Network Delay Time 解题报告(Python)

    [LeetCode]743. Network Delay Time 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: ht ...

  8. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  9. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

随机推荐

  1. 原型模式故事链--new一个对象的过程

    上一个总标题:https://segmentfault.com/a/11...提问:你有对象了吗?答:没有.笨!new一个不就好了吗! 问题点:为什么我要理解new一个对象的过程?答:不理解这个过程, ...

  2. window nginx 简单搭建服务器访问静态资源

    nginx命令: 启动: start nginx 停止:nginx -s stop ||  nginx -s quit 注:stop是快速停止nginx,可能并不保存相关信息:quit是完整有序的停止 ...

  3. lunix或者centos服务器下如何下载自己在github上面的项目代码

    1.在github找到项目压缩包下载地址 打开自己的github主页找到需要下载的项目首页,如图所示,找到zip下载地址(ps:如何找这个地址我就不多说了,了解过一点html的同学肯定很容易可以找到) ...

  4. c++对c的拓展_命名空间_简单使用

    名字的控制:c可使用static关键字使该关键字在本单元内可见,c++则使用命名空间对名字的可见性及产生进行控制 命名空间:控制标识符的作用域(本质上就是一个作用域) 使用特点:1.必须定义在全局范围 ...

  5. mybatis-day1入门案例

    首先应先创建maven工程 (jar包要导入,五个核心jar包) 如果测试运行时出现了不支持版本5,则要修改以下内容 类的路径如下 1.配置pom.xml依赖 <?xml version=&qu ...

  6. LC-454

    题目 给你四个整数数组 nums1.nums2.nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 <= i, j, k, l < ...

  7. STL空间分配器源码分析(二)mt_allocator

    一.简介 mt allocator 是一种以2的幂次方字节大小为分配单位的空间配置器,支持多线程和单线程.该配置器灵活可调,性能高. 分配器有三个通用组件:一个描述内存池特性的数据,一个包含该池的策略 ...

  8. 安卓记账本开发学习day5之版本兼容问题

    安卓5.0以上版本想要隐藏DatePicker头布局的写法比较复杂,需要一层一层隐藏 int headerId = getContext().getResources().getIdentifier( ...

  9. 安卓记账本开发学习day2

    今天遇到了xml文件报错,Wrong orientation? No orientation specified, and the default is horizontal, yet this la ...

  10. JavaWeb学习day1-web入门&服务器安装

    初步了解了web的发展历程,对比分析学习了动态页面与静态页面的优缺点. 选择安装使用最广泛的Tomcat 安装流程: 1.打开官网:https://tomcat.apache.org/ 2.选择下载版 ...