poj3162(树形dp+线段树求最大最小值)
时间:2019-08-28
本文章向大家介绍poj3162(树形dp+线段树求最大最小值),主要包括poj3162(树形dp+线段树求最大最小值)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目链接:https://vjudge.net/problem/POJ-3162
题意:给一棵树,求每个结点的树上最远距离,记为a[i],然后求最大区间[l,r]满足区间内的max(a[i])-min(a[i])<=M。
思路:第一步向hdoj2196那题一样树形dp求出每个结点的最长距离,我的另一篇博客中有写到https://www.cnblogs.com/FrankChen831X/p/11375572.html。求出最远距离a[i]后,建立线段树维护区间的最大最小值。然后用两个指针i,j遍历一遍,每次求出[i,j]的最大最小值ans1和ans2,更新答案,因为j每次不用初始化,总复杂度为O(nlogn)。
AC代码:
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; const int maxn=1e6+5; const LL inf=0x3f3f3f3f3f3f3f3f; int n,ans,cnt,head[maxn],pt[maxn],a[maxn]; LL M,dp[maxn][3],ans1,ans2; struct node1{ int v,nex; LL w; }edge[maxn<<1]; struct node2{ int l,r; LL Max,Min; }tr[maxn<<2]; void adde(int u,int v,LL w){ edge[++cnt].v=v; edge[cnt].w=w; edge[cnt].nex=head[u]; head[u]=cnt; } void dfs1(int u,int fa){ for(int i=head[u];i;i=edge[i].nex){ int v=edge[i].v; LL w=edge[i].w; if(v==fa) continue; dfs1(v,u); if(w+dp[v][0]>dp[u][0]){ dp[u][1]=dp[u][0]; dp[u][0]=w+dp[v][0]; pt[u]=v; } else if(w+dp[v][0]>dp[u][1]) dp[u][1]=w+dp[v][0]; } } void dfs2(int u,int fa){ for(int i=head[u];i;i=edge[i].nex){ int v=edge[i].v; LL w=edge[i].w; if(v==fa) continue; if(v!=pt[u]) dp[v][2]=w+max(dp[u][0],dp[u][2]); else dp[v][2]=w+max(dp[u][1],dp[u][2]); dfs2(v,u); } } void pushup(int v){ tr[v].Max=max(tr[v<<1].Max,tr[v<<1|1].Max); tr[v].Min=min(tr[v<<1].Min,tr[v<<1|1].Min); } void build(int v,int l,int r){ tr[v].l=l,tr[v].r=r; if(l==r){ tr[v].Max=tr[v].Min=a[l]; return; } int mid=(l+r)>>1; build(v<<1,l,mid); build(v<<1|1,mid+1,r); pushup(v); } void query(int v,int l,int r){ if(l<=tr[v].l&&r>=tr[v].r){ ans1=max(ans1,tr[v].Max); ans2=min(ans2,tr[v].Min); return; } int mid=(tr[v].l+tr[v].r)>>1; if(l<=mid) query(v<<1,l,r); if(r>mid) query(v<<1|1,l,r); } int main(){ scanf("%d%lld",&n,&M); for(int i=2;i<=n;++i){ int v;LL w; scanf("%d%lld",&v,&w); adde(i,v,w); adde(v,i,w); } dfs1(1,0); dfs2(1,0); for(int i=1;i<=n;++i) a[i]=max(dp[i][0],dp[i][2]); build(1,1,n); int j=1; for(int i=1;i<=n;++i){ while(j<=n){ ans1=0,ans2=inf; query(1,i,j); if(ans1-ans2>M) break; ++j; } ans=max(ans,j-i); } printf("%d\n",ans); return 0; }
原文地址:https://www.cnblogs.com/FrankChen831X/p/11423208.html
- use vue vuex vue-router, not use webpack
- 从尾到头打印链表
- Webpack+Vue如何导入Jquery和Jquery的第三方插件
- [Hadoop大数据]——Hive部署入门教程
- Vuex原来可以这样上手
- 《Hive编程指南》—— 读后总结
- Event(事件)的传播与冒泡
- [Hadoop大数据]——Hive数据的导入导出
- 区块链技术在电子游戏与博彩行业备受追捧 有望实现数字商品货币化
- vue原来可以这样上手
- [Hadoop大数据]——Hive连接JOIN用例详解
- 扑克牌的顺子
- 数组前半部分和后半部分有序的全排序
- restful Api 风格契约设计器:Swagger-editor和swagger-ui的应用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Redis在分布式项目中的应用
- 常见的Form表单提交方式
- 基于RPC实现服务的注册、发布和消费
- HttpClient技术
- JsonP------实现跨域请求
- ActiveMQ—基于Java的消息传递服务器
- SpringMVC知识体系搭建
- 你分得清MySQL普通索引和唯一索引了吗?
- 基于Dubbo的CRUD案例
- 在javaEE中,实现用户登陆功能的实现
- JavaEE中,实现登录时进行校验验证码的功能
- JavaEE中为删除数据操作与退出操作添加确认提示框
- JavaWeb中的实现页面跳转的同卵双胞胎兄弟——重定向与请求转发
- JavaWeb中的异卵双胞胎——监听器与过滤器
- JavaEE中的el 表达式以及JSTL详解