题意:给出一棵无根树,每个节点有一个权值,现在要让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-8
# define MOD 1000000007
# define INF 1000000000
# 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<<1,l,mid
# define rch p<<1|1,mid+1,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=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
const int N=200005;
//Code begin...struct Edge{int p, next;}edge[N<<1];
int node[N], head[N], cnt=1, 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]=1;if (node[x]<val) tag[x]=1, ++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]=1;int f=0, s=0;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,0); mem(dp,0); mem(flag,false); mem(tag,0); sum=ans=0;dfs1(1,0,x); dfs2(1,0,x);return ans>=K;
}
int main ()
{int u, v;scanf("%d%d",&n,&K);FOR(i,1,n) scanf("%d",node+i), date[i]=node[i];FO(i,1,n) scanf("%d%d",&u,&v), add_edge(u,v), add_edge(v,u);sort(date+1,date+n+1);int l=1, r=n+1, mid;while (l<r) {mid=(l+r)>>1;if (l==mid) break;if (check(date[mid])) l=mid;else r=mid;}printf("%d\n",date[l]);return 0;
}

View Code

转载于:https://www.cnblogs.com/lishiyao/p/6971255.html

Codeforces 627D Preorder Test(二分+树形DP)相关推荐

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

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

  2. 吉吉王国(二分+树形dp)

    吉吉王国 题意: n个点,m个边,有边权,现在要求叶子节点无法与1号点连通,要求切断的总长度不能超过m,且切断的最长的长度尽可能断 题解: 题意的前半部分可以确定是树形dp,后半部分可以确定为是二分 ...

  3. CodeForces - 1324F Maximum White Subtree(树形dp)

    题目链接:点击查看 题目大意:给出 n 个点组成的树,每个点都有一个颜色,非黑即白,现在问对于每个点而言,选出一个连通块,使得白色点的个数与黑色点的个数做差最大 题目分析:记录一下div3的第一次ak ...

  4. CodeForces - 1485E Move and Swap(树形dp)

    题目链接:点击查看 题目大意:给出一棵有根树,每个节点都有权值,满足所有叶子结点到根节点的距离相同,初始时在根节点有两个硬币,分别是红色和蓝色,每次可以执行如下操作: 将红色硬币移动到任意一个子节点 ...

  5. Codeforces - 706B - Interesting drink - 二分 - 简单dp

    https://codeforces.com/problemset/problem/706/B 因为没有看见 $x_i$ 的上限是 $10^5$ ,就用了二分去做,实际上这道题因为可乐的价格上限是 $ ...

  6. Codeforces 1276D/1259G Tree Elimination (树形DP)

    题目链接 http://codeforces.com/contest/1276/problem/D 题解 我什么DP都不会做,吃枣药丸-- 设\(f_{u,j}\)表示\(u\)子树内,\(j=0\) ...

  7. P4383-[八省联考2018]林克卡特树【wqs二分,树形dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P4383 题目大意 nnn个点的一棵树,要求删除kkk条边然后接上kkk条边权为000的边后形成的树上选择一对(p, ...

  8. E. Xenon's Attack on the Gangs,Codeforces Round #614 (Div. 2),树形dp

    E. Xenon's Attack on the Gangs http://codeforces.com/contest/1293/problem/E On another floor of the ...

  9. 【CodeForces - 697D】Puzzles(树形dp,期望dp)

    题目大意: 给定一棵树,从1开始,按DFS的方式访问这棵树  每次从父亲节点随机访问儿子,问每个节点被访问到的时间的期望 输入:第一行一个数n,代表n个节点.第二行n-1个数p2,p3,p4,p5.. ...

  10. BZOJ 4753 二分+树形DP

    思路: 先二分答案 f[x][j]表示在x的子树里选j个点 f[x][j+k]=max(f[x][j+k],f[x][j]+f[v[i]][k]); 初始化 x!=0 -> f[x][1]=p[ ...

最新文章

  1. 从1的补码说起计算机的数制
  2. mysql 事务补偿_TCC补偿性策略_彻底学习数据库事务 seata分布式事务 共享 排它锁 死锁 索引 Spring事务 隔离级别等_MySQL视频-51CTO学院...
  3. python中list作为全局变量无需global声明的原因
  4. netcore 学习
  5. 第6章-一阶多智体系统一致性-->6.5 带有领航者系统一致性
  6. php errno 28,php7.28 编译出错 一直通不过去
  7. PHP在Windows环境下获取GMT时间
  8. w10计算机无法打印,老司机解答win10系统电脑无法打印的详细技巧
  9. basic code
  10. 2014 Multi-University Training Contest 1 — D. Task
  11. leetcode950. Reveal Cards In Increasing Order
  12. 对JQuery中Ajax应用与jQuery插件的理解与笔记
  13. openslide read region 出现黑块 解决办法
  14. 软件定义存储(SDS)学习一
  15. 【大数据实战】flume 数据采集
  16. java Date与 double 互转
  17. 银行业“业务连续性”管理(上篇)
  18. 亚马逊下架产品还能重新恢复吗?
  19. 使用API 在zabbix监控系统中查看,创建及删除监控主机
  20. DBus daemon 启动(三)

热门文章

  1. django(三):配置文件settings.py、初始化数据库
  2. c++ 银行管理系统
  3. nyoj 949哈利波特(细节题)
  4. 2010湖南省第六界程序设计大赛 B题 --弟弟的作业(nyoj663)
  5. qpushbutton设置两个图标_苹果手机的月亮图标有什么功能?原来这么好用,不会真的太浪费了...
  6. python之路day9_Python之路,Day7 - 面向对象编程进阶
  7. Day004 20210209-20210217
  8. linux mongo 添加用户名和密码,mongodb3.4 安装及用户名密码设置
  9. 阿里云云计算 41 阿里云CDN的工作原理
  10. Nesterov Momentum牛顿动量法