二分枚举答案,判定答案是否合法

贪心:每一个叶子只能经过一遍,因此叶子的顺序一定是一个dfs序,即走完一棵子树中的所有叶子才会到子树外

根据这个贪心可以dp,设$f[k][l][r]$表示仅考虑$k$的子树,$l$和$r$为第一个和最后一个叶子到根的距离,时间复杂度大约有$o(n^{4或5})$,无法通过

考虑优化,将所有$f[k][l][r]=1$的$(l,r)$记录下来,若存在$l'\le l$且$r'\le r$,$(l,r)$一定没有意义,这可以用一个单调栈来维护,那么同一个$l/r$所对应的$r/l$最多只有1个

转移考虑合并,不妨假设左子树比右子树小,枚举左子树中的$(l_{1},r_{1})$,对于右子树中的$(l_{2},r_{2})$,有两种转移的可能:1.若$r_{1}+l_{2}+v_{ls}+v_{rs}\le ans$,转移到$(l_{1}+v_{ls},r_{2}+v_{rs})$;2.若$l_{1}+r_{2}+v_{ls}+v_{rs}\le ans$,转移到$(l_{2}+v_{rs},r_{1}+v_{ls})$

可以利用单调性来优化,即找到满足$l_{2}\le ans-r_{1}-v_{ls}-v_{rs}$且$r_{2}$最小的位置(第一种转移),那么每一组$(l_{1},r_{1})$最多转移到$k$中的两个状态(反之同理),即有$|state[k]|\le 2\min(|state[ls]|,|state[rs]|)$,空间复杂度为$o(n\log_{2}n)$,时间复杂度即为空间复杂度乘上二分,为$o(n\log^{\ 2}_{2}n)$

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 200005
4 #define ll long long
5 #define fi first
6 #define se second
7 vector<pair<ll,ll> >v,f[N];
8 int n,x,ls[N],rs[N],w[N];
9 ll ans;
10 void dfs(int k){
11 f[k].clear();
12 if ((!ls[k])&&(!rs[k])){
13 f[k].push_back(make_pair(0,0));
14 return;
15 }
16 dfs(ls[k]);
17 dfs(rs[k]);
18 ll s=ans-w[ls[k]]-w[rs[k]];
19 for(int i=0,j=0;i<f[ls[k]].size();i++){
20 while ((j<f[rs[k]].size())&&(f[rs[k]][j].fi<=s-f[ls[k]][i].se))j++;
21 if ((j)&&(f[rs[k]][j-1].fi<=s-f[ls[k]][i].se))f[k].push_back(make_pair(f[ls[k]][i].fi+w[ls[k]],f[rs[k]][j-1].se+w[rs[k]]));
22 }
23 swap(ls[k],rs[k]);
24 for(int i=0,j=0;i<f[ls[k]].size();i++){
25 while ((j<f[rs[k]].size())&&(f[rs[k]][j].fi<=s-f[ls[k]][i].se))j++;
26 if ((j)&&(f[rs[k]][j-1].fi<=s-f[ls[k]][i].se))f[k].push_back(make_pair(f[ls[k]][i].fi+w[ls[k]],f[rs[k]][j-1].se+w[rs[k]]));
27 }
28 if (!f[k].size())return;
29 sort(f[k].begin(),f[k].end());
30 v.clear();
31 v.push_back(f[k][0]);
32 for(int i=1;i<f[k].size();i++)
33 if (f[k][i].se<v[(int)v.size()-1].se)v.push_back(f[k][i]);
34 f[k]=v;
35 }
36 bool pd(ll k){
37 ans=k;
38 dfs(1);
39 return f[1].size();
40 }
41 int main(){
42 scanf("%d",&n);
43 for(int i=2;i<=n;i++){
44 scanf("%d%d",&x,&w[i]);
45 if (!ls[x])ls[x]=i;
46 else rs[x]=i;
47 }
48 ll l=0,r=1LL*N*N;
49 while (l<r){
50 ll mid=(l+r>>1);
51 if (pd(mid))r=mid;
52 else l=mid+1;
53 }
54 printf("%lld",l);
55 }

[atAGC007E]Shik and Travel的更多相关文章

  1. 【AtCoder Grand Contest 007E】Shik and Travel [Dfs][二分答案]

    Shik and Travel Time Limit: 50 Sec  Memory Limit: 512 MB Description 给定一棵n个点的树,保证一个点出度为2/0. 遍历一遍,要求每 ...

  2. AGC007E Shik and Travel 解题报告

    AGC007E Shik and Travel 题目大意:\(n\) 个点的二叉树,每个点要么两个儿子,要么没有儿子,每条边有边权. 你从 \(1\) 号节点出发,走到一个叶子节点.然后每一天,你可以 ...

  3. [AT2172] [agc007_e] Shik and Travel

    题目链接 AtCoder:https://agc007.contest.atcoder.jp/tasks/agc007_e 洛谷:https://www.luogu.org/problemnew/sh ...

  4. AtCoder Grand Contest 007 E:Shik and Travel

    题目传送门:https://agc007.contest.atcoder.jp/tasks/agc007_e 题目翻译 现在有一个二叉树,除了叶子每个结点都有两个儿子.这个二叉树一共有\(m\)个叶子 ...

  5. AT2172 Shik and Travel

    题目描述: luogu 题解: 二分+暴力$vector$+$dfs$. 记录下所有可能的子树内合法方案,双指针+归并合并. 代码: #include<vector> #include&l ...

  6. [AGC007E] Shik and Travel

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

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

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

  8. AtCoder Grand Contest 007

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

  9. AtCoder Grand Contest

    一句话题解 QwQ主要是因为这篇文章写的有点长……有时候要找某一个题可能不是很好找,所以写了这个东西. 具体的题意.题解和代码可以再往下翻._(:з」∠)_ AGC 001 C:枚举中点/中边. D: ...

随机推荐

  1. 那些我用Windows时必备的软件

    那些我用Windows时必备的软件 使用Windows多年来,自己发现了许多不错的小软件,在此做一个备份清单,方便今后装新机. 起源 \(hadow\)ock$ 越过高墙的小飞机 Google Chr ...

  2. Data Management Tools(数据管理工具)《二》

    (数据管理工具)<二> 点击跳转(数据管理工具)<一> 16.打包 # Process: 共享包 arcpy.SharePackage_management("&qu ...

  3. NX7.5 使用UF_MODL_create_proj_curves创建投影曲线

    1 [DllImport("libufun.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet ...

  4. ThreadLocalRandom类原理分析

    1.Random类及其局限性 public int nextInt(int bound) { if (bound <= 0) throw new IllegalArgumentException ...

  5. 【数据结构与算法Python版学习笔记】树——利用二叉堆实现优先级队列

    概念 队列有一个重要的变体,叫作优先级队列. 和队列一样,优先级队列从头部移除元素,不过元素的逻辑顺序是由优先级决定的. 优先级最高的元素在最前,优先级最低的元素在最后. 实现优先级队列的经典方法是使 ...

  6. 类图示例-订单系统 / Class Diagram - Order System

    类图示例-订单系统 / Class Diagram - Order System 什么是类图? 类图通过显示它的类和它们之间的关系来概述系统.类图是静态的 - 它们显示交互的内容,但不显示交互时会发生 ...

  7. 五分钟搞懂spring-cloud-square

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 初识spring-cloud-square 2021年 ...

  8. 单片机stm32 USART串口实际应用解析

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...

  9. 常用JAVA API :HashSet 和 TreeSet

    set容器的特点是不包含重复元素,也就是说自动去重. HashSet HashSet基于哈希表实现,无序. add(E e)//如果容器中不包含此元素,则添加. clear()//清空 contain ...

  10. linux shell exec 关联文件描述符

    在写shell脚本时,如果多个命令的输入或输出都是同一个文件,而这个文件的路径和名字都很长,则需要书写很多次同样的路径会很浪费时间,我们可以使用exec命令来关联一个自定义的文件描述符到一个特定的文件 ...