题目传送门:https://agc007.contest.atcoder.jp/tasks/agc007_e

题目翻译

现在有一个二叉树,除了叶子每个结点都有两个儿子。这个二叉树一共有\(m\)个叶子,你需要从\(1\)号点出发,旅行\(m+1\)天后回到\(1\)号结点,其中前\(m\)天每天需要在叶子节点结束,并且每个叶子结点只允许被经过一次,每条边只允许被经过两次,边有边权,旅行的费用即为两点之间简单路径上权值之和,然后问你费用最大的一天最小可以是多少。第一天和最后一天免费。

题解

嗯,这又是一道题解题……

我们考虑二分答案,那么问题就转化成了怎么判断“每天花费都不超过\(limit\)是否可以完成旅途”。由于每条边只允许被经过两次 ,所以每个子树只允许被进出一次各一次。我们设\(f_{ijk}\)表示\(i\)号点子树第一次进去花费\(j\),出来花费\(k\),内部叶子节点走来走去不超过\(limit\)是否可以做到。因为边权过大,状态存不下来,所以我们用\(vector\)存三元组\(<i,j,k>\)来表示这个状态为真。当\(j\)相同时我们只存较小的\(k\),所以状态个数只会有\(NlogN\)个。然后每次由两个儿子转移更新自己可以用归并排序,按\(j\)从小打大排。

时间复杂度:\(O(NlogNlogANS)\)

空间复杂度:\(O(NlogN)\)

代码如下:

#include <vector>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<pll> vp;
#define fr first
#define sc second const int maxn=131073; int n,tot;
ll dis[maxn];
int son[maxn][2],num[maxn];
ll l,r=1ll*maxn*maxn,limit; vp f[maxn]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} vp dp(vp a,vp b) {
vp res;res.clear();
int x=a.size(),y=b.size(),st1=0,st2=0;
if(!y)return res;
while(st1!=x) {
while(st2!=y&&a[st1].sc+b[st2].fr<=limit)st2++;
if(st2)st2--;
if(a[st1].sc+b[st2].fr<=limit)res.push_back(make_pair(a[st1].fr,b[st2].sc));
st1++;
}
return res;
} void insert(vp &a,pll b) {
if(a.empty())a.push_back(b);
else if(a.back().fr==b.fr)a.back().sc=min(a.back().sc,b.sc);
else if(b.sc<a.back().sc)a.push_back(b);
} vp merge(vp a,vp b) {
vp res;res.clear();
int x=a.size(),y=b.size(),st1=0,st2=0;
while(st1!=x&&st2!=y) {
if(a[st1].fr<b[st2].fr)insert(res,a[st1++]);
else insert(res,b[st2++]);
}
while(st1!=x)insert(res,a[st1++]);
while(st2!=y)insert(res,b[st2++]);
return res;
} void dfs(int u) {
if(!num[u]) {
f[u].clear();
f[u].push_back(make_pair(dis[u],dis[u]));
return;
}
dfs(son[u][0]),dfs(son[u][1]);limit+=dis[u]*2;
vp tmp1=dp(f[son[u][0]],f[son[u][1]]);
vp tmp2=dp(f[son[u][1]],f[son[u][0]]);
f[u]=merge(tmp1,tmp2);
limit-=dis[u]*2;
} bool check() {
dfs(1);
if(!f[1].empty())return 1;
return 0;
} int main() {
n=read();
for(int i=2;i<=n;i++) {
int fa=read(),v=read();
dis[i]=dis[fa]+v;
son[fa][num[fa]++]=i;
}
while(l<r) {
limit=(l+r)>>1;
if(check())r=limit;
else l=limit+1;
}
printf("%lld\n",r);
return 0;
}

AtCoder Grand Contest 007 E:Shik and Travel的更多相关文章

  1. AtCoder Grand Contest 007

    AtCoder Grand Contest 007 A - Shik and Stone 翻译 见洛谷 题解 傻逼玩意 #include<cstdio> int n,m,tot;char ...

  2. AtCoder Grand Contest 009 D:Uninity

    题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_d 题目翻译 定义只有一个点的树权值为\(0\),若干棵(可以是\(0\)棵)权值为\(k\) ...

  3. AtCoder Grand Contest 009 E:Eternal Average

    题目传送门:https://agc009.contest.atcoder.jp/tasks/agc009_e 题目翻译 纸上写了\(N\)个\(1\)和\(M\)个\(0\),你每次可以选择\(k\) ...

  4. AtCoder Grand Contest 004 C:AND Grid

    题目传送门:https://agc004.contest.atcoder.jp/tasks/agc004_c 题目翻译 给你一张网格图,指定的格子是紫色的,要求你构造出两张网格图,其中一张你可以构造一 ...

  5. AtCoder Grand Contest 014 D:Black and White Tree

    题目传送门:https://agc014.contest.atcoder.jp/tasks/agc014_d 题目翻译 给你一棵树,每次任选一个点染色,先手染白色,后手染黑色.如果最后存在一个白色的点 ...

  6. AtCoder Grand Contest 028 A:Two Abbreviations

    题目传送门:https://agc028.contest.atcoder.jp/tasks/agc028_a 题目翻译 给你两个串\(s\)与\(t\),长度分别为\(n,m\).问你存不存在一个串长 ...

  7. AtCoder Grand Contest 002 F:Leftmost Ball

    题目传送门:https://agc002.contest.atcoder.jp/tasks/agc002_f 题目翻译 你有\(n*k\)个球,这些球一共有\(n\)种颜色,每种颜色有\(k\)个,然 ...

  8. AtCoder Grand Contest 013 C:Ants on a Circle

    题目传送门:https://agc013.contest.atcoder.jp/tasks/agc013_c 题目翻译 给你一个周长为\(L\)的圆,有\(N\)只蚂蚁在圆上爬,速度为一单位距离每秒. ...

  9. AtCoder Grand Contest 010 C:Cleaning

    题目传送门:https://agc010.contest.atcoder.jp/tasks/agc010_c 题目翻译 给你一棵树,每个点有个权值,每次操作可以选择两个度数为\(1\)的结点,然后让这 ...

随机推荐

  1. Git安装及SSH Key管理之Mac篇

    1.下载git客户端,下载地址为:https://git-scm.com/download/mac 2.打开安装包,可以看到此时的界面为:   我们需要把.pkg的安装包安装到系统当中.我双击了安装包 ...

  2. class文件无论是32位还是64位jdk编译出来的,都可以通用

    class文件无论是32位还是64位jdk编译出来的,都可以通用 学习了:https://blog.csdn.net/z3111001358/article/details/53364066 java ...

  3. 上传图片/文件到server

    package yao.camera.util; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; impo ...

  4. vue2.0 flexible.js + rem 进行自适应开发

    1.在页面中引入flexible.js base.js /** * flexible.js 阿里前端自适应解决方案 */ ;(function(win, lib) { var doc = win.do ...

  5. Populating Next Right Pointers in Each Node I, II——生成next树

    1. Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode * ...

  6. 【转载】ASP和ASP.NET根本区别

    ASP.NET和ASP的最大区别在于编程思维的转换,而不仅仅在于功能的增强.ASP使用VBS/JS这样的脚本语言混合html来编程,而那些脚本语言属于弱类型.面向结构的编程语言,而非面向对象,这就明显 ...

  7. [Codevs 1230]元素查找(手写哈希表)

    题目连接:http://codevs.cn/problem/1230/ 说白了就是要我们自己手写一个哈希表的数据结构来实现加入和查找功能.map也能直接过(我第一次写就是用map骗AC的) 提一下个人 ...

  8. libraries_v140_x64_py35_1.0.1.tar.bz2 libraries_v120_x64_py27_1.1.0.tar 下载链接以及百度云下载链接

    下载链接 wget  -c  https://github.com/willyd/caffe-builder/releases/download/v1.0.1/libraries_v140_x64_p ...

  9. 无线(仅WIFI)攻击思路总结

    从事信息安全相关工作5年了,虽然主要工作是安全产品售前.安全服务等方向,但既然选择了安全,想必都是有点黑客情节的,因此也前前后后杂七杂八的学了点东西.最近在研究无线(主要是WIFI)安全,相关书籍看了 ...

  10. 目标检测之hough forest---霍夫森林(Hough Forest)目标检测算法

     Hough Forest目标检测一种比较时兴的目标检测算法,Juergen Gall在2009的CVPR上提出. Hough Forest听上去像hough变换+Random Forest的结合体, ...