题意:给出一棵无根树,每个节点有一个权值,现在要让dfs序的前k个结点的最小值最大,求出这个值。

考虑二分答案,把>=答案的点标记为1,<答案的点标记为0,现在的任务时使得dfs序的前k个节点都为1.

考虑树形DP。

用dp[u]表示从节点u开始在子树中进行dfs最多可以经过多少个为1的结点,显然,若某一个子树中节点全为1,那么这个可以加到dp[u]中,此外还可以在不全为1的子树中挑选一个加到dp[u]上。

那么答案就是从标记为1的节点当做根,选两颗不完全子树和所有的完全子树(包括从父亲向上的部分)。

那么如果从父亲向上的部分是不完全子树呢,那等价于从这颗不完全子树上的一个深度最小的点做上面的计算一下。所以不需要考虑从父亲向上的部分是不完全子树这个情况。

时间复杂度O(nlogn).

# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <bitset>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int N=;
//Code begin... struct Edge{int p, next;}edge[N<<];
int node[N], head[N], cnt=, dp[N], date[N], siz[N], tag[N], sum, n, K, ans;
bool flag[N]; void add_edge(int u, int v){edge[cnt].p=v; edge[cnt].next=head[u]; head[u]=cnt++;}
void dfs1(int x, int fa, int val){
siz[x]=;
if (node[x]<val) tag[x]=, ++sum;
if (node[x]<val) flag[x]=true;
for (int i=head[x]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==fa) continue;
dfs1(v,x,val); siz[x]+=siz[v]; tag[x]+=tag[v]; flag[x]|=flag[v];
}
}
void dfs2(int x, int fa, int val){
dp[x]=;
int f=, s=;
for (int i=head[x]; i; i=edge[i].next) {
int v=edge[i].p;
if (v==fa) continue;
dfs2(v,x,val);
if (!flag[v]) dp[x]+=siz[v];
else if (node[v]>=val) {
if (dp[v]>f) s=f, f=dp[v];
else if (dp[v]>s) s=dp[v];
}
}
dp[x]+=f;
if (node[x]>=val) {
if (tag[x]==sum) ans=max(ans,dp[x]+s+n-siz[x]);
else ans=max(ans,dp[x]+s);
}
}
bool check(int x){
mem(siz,); mem(dp,); mem(flag,false); mem(tag,); sum=ans=;
dfs1(,,x); dfs2(,,x);
return ans>=K;
}
int main ()
{
int u, v;
scanf("%d%d",&n,&K);
FOR(i,,n) scanf("%d",node+i), date[i]=node[i];
FO(i,,n) scanf("%d%d",&u,&v), add_edge(u,v), add_edge(v,u);
sort(date+,date+n+);
int l=, r=n+, mid;
while (l<r) {
mid=(l+r)>>;
if (l==mid) break;
if (check(date[mid])) l=mid;
else r=mid;
}
printf("%d\n",date[l]);
return ;
}

Codeforces 627D Preorder Test(二分+树形DP)的更多相关文章

  1. 8VC Venture Cup 2016 - Final Round D. Preorder Test 二分 树形dp

    Preorder Test 题目连接: http://www.codeforces.com/contest/627/problem/D Description For his computer sci ...

  2. 【bzoj5174】[Jsoi2013]哈利波特与死亡圣器 二分+树形dp

    题目描述 给你一棵以1为根的有根树,初始除了1号点为黑色外其余点均为白色.Bob初始在1号点.每次Alice将其中至多k个点染黑,然后Bob移动到任意一个相邻节点,重复这个过程.求最小的k,使得无论B ...

  3. 【题解】hdu 3586 Information Disturbing 二分 树形dp

    题目描述 Information DisturbingTime Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/65536 K (Java ...

  4. codeforces 161D Distance in Tree 树形dp

    题目链接: http://codeforces.com/contest/161/problem/D D. Distance in Tree time limit per test 3 secondsm ...

  5. codeforces 337D Book of Evil (树形dp)

    题目链接:http://codeforces.com/problemset/problem/337/D 参考博客:http://www.cnblogs.com/chanme/p/3265913 题目大 ...

  6. HDU 3586 Information Disturbing(二分+树形dp)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...

  7. HDU 5682 zxa and leaf 二分 树形dp

    zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...

  8. bzoj 2067: [Poi2004]SZN【贪心+二分+树形dp】

    第一问就是Σ(deg[u]-1)/2+1 第二问是二分,判断的时候考虑第一问的贪心规则,对于奇度数的点,两两配对之后一条延伸到上面:对于欧度数的点,两两配对或者deg[u]-2的点配对,然后一条断在这 ...

  9. Codeforces 1276D - Tree Elimination(树形 dp)

    Codeforces 题面传送门 & 洛谷题面传送门 繁琐的简单树形 dp(大雾),要是现场肯定弃了去做 F 题 做了我一中午,写篇题解纪念下. 提供一种不太一样的思路. 首先碰到这样的题肯定 ...

随机推荐

  1. WPF 动画:同为控件不同命 - 简书

    原文:WPF 动画:同为控件不同命 - 简书 1. 及格与优秀 读大学的时候,有一门课的作业是用 PPT 展示. 但是我们很多同学都把 PPT 当做 Word 来用,就单纯地往里面堆文字. 大家都单纯 ...

  2. java开发工具使用

    一.MyEclipse软件的使用 1)ctrl+n新建文件 2)ctrl+d删除一行 3)alt+/提示补齐 (main/syso/syse/for遍历最近的数组) 4)ctrl+shift+f格式化 ...

  3. 2288: 【POJ Challenge】生日礼物

    2288: [POJ Challenge]生日礼物 https://lydsy.com/JudgeOnline/problem.php?id=2288 分析: 贪心+堆+链表. 首先把序列变一下,把相 ...

  4. superset 安装测试,基于windows 和 centos7.x

    1.刚开始在windows平台测试搭建,报各种问题,搭建可以参考官网https://superset.incubator.apache.org/installation.html#deeper-sql ...

  5. itop4412学习-上层应用多任务开发

    1. 首先搭建虚拟机VMWARE12.0+UBUNTU16.04,不过报错了,说是要关闭计算机(非重启)-- 进入BIOS -- 设置BIOS的虚拟化(不打开,默认是工作在32位模式的,virtual ...

  6. kali安装后相关软件的配置

    更新软件apt-get updateapt-get upgrade安装输入法apt-get install ibus-pinyin apt-get install netspeed安装GNOMEapt ...

  7. loj2538 「PKUWC 2018」Slay the Spire

    pkusc 快到了--做点题涨涨 rp. ref我好菜啊QAQ. 可以发现期望只是一个幌子.我们的目的是:对于所有随机的选择方法(一共 \(\binom{2n}{m}\)种),这些选择方法都最优地打出 ...

  8. springboot入门之一:环境搭建(续)

    在上篇博客中从springboot的入门到运行一个springboot项目进行了简单讲述,详情请查看“springboot入门之一”.下面继续对springboot做讲述. 开发springboot测 ...

  9. Appium 安卓计算器demo

    package testProject; import org.openqa.selenium.*; import org.openqa.selenium.remote.DesiredCapabili ...

  10. C++进阶训练——停车收费系统设计

    一.简介 经过一段时间的c++基础学习,是时候做一个较为全面的.运用c++功能的较复杂的项目练练手了. 运用软件:Visual Studio   (VS). 题目:c++停车收费系统设计(某本编程书进 ...