bzoj 2500: 幸福的道路 动态规划+单调栈
来源:互联网 发布:打电话变声软件下载 编辑:程序博客网 时间:2024/05/28 05:14
题意
给出一棵树,每条边都有一个长度。我们规定每个点的权值为从该点开始走过的一条最长的路径的长度。
求一个最长的区间[l,r],使得[l,r]里面点权的最大值和最小值只差不超过m。
n<=1000000
分析
首先我们要把点权求出来。
那么我们设1为根节点,用两个数组fir[i]和sec[i]维护从节点i开始最长的路径和次长的路径。
第一次先求出起点为i终点在i的子树内的最长路和次长路,第二次再求出每个节点往其父节点走的最长路径。
接着就要求最大的区间,这里我一开始的想法是用数据结构来维护,set或者线段树什么的应该都行,但是我们注意到n<=1000000,则这么干有可能会超时。
那么我们就改用单调栈来维护最大值和最小值。
第一个单调栈保证里面的元素严格递增,第二个单调栈保证里面的元素严格递减,那么最大值就是第二个单调栈的栈底,最小值就是第一个单调栈的栈顶,我们只需要每次插入i时同时维护这两个单调栈即可。
1A大法好!!!
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define N 1000005using namespace std;int n,m,last[N],cnt;struct edge{int to,len,next;}e[N*2];struct stack{int len,id;}stack1[N],stack2[N];struct data{int num,len;}fir[N],sec[N];void addedge(int u,int v,int len){ e[++cnt].to=v;e[cnt].len=len;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].len=len;e[cnt].next=last[v];last[v]=cnt;}void dfs1(int x,int fa){ for (int i=last[x];i;i=e[i].next) { if (e[i].to==fa) continue; dfs1(e[i].to,x); if (fir[e[i].to].len+e[i].len>fir[x].len) { sec[x]=fir[x]; fir[x].len=fir[e[i].to].len+e[i].len; fir[x].num=e[i].to; }else if (fir[e[i].to].len+e[i].len>sec[x].len) { sec[x].len=fir[e[i].to].len+e[i].len; sec[x].num=e[i].to; } }}void dfs2(int x,int fa,int len){ int w; if (fir[fa].num==x) w=sec[fa].len+len; else w=fir[fa].len+len; if (w>fir[x].len) { sec[x]=fir[x]; fir[x].len=w; fir[x].num=fa; }else if (w>sec[x].len) { sec[x].len=w; sec[x].num=fa; } for (int i=last[x];i;i=e[i].next) { if (e[i].to==fa) continue; dfs2(e[i].to,x,e[i].len); }}int main(){ scanf("%d%d",&n,&m); for (int i=2;i<=n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,i,y); } dfs1(1,0); dfs2(1,0,0); int head1=1,tail1=0,head2=1,tail2=0,l=1,ans=0; for (int i=1;i<=n;i++) { int w=fir[i].len; while (head1<=tail1&&stack1[tail1].len>=w) tail1--; tail1++; stack1[tail1].len=w; stack1[tail1].id=i; while (head2<=tail2&&stack2[tail2].len<=w) tail2--; tail2++; stack2[tail2].len=w; stack2[tail2].id=i; while (stack2[head2].len-stack1[head1].len>m) if (stack1[head1].id<stack2[head2].id) { l=stack1[head1].id+1; head1++; }else { l=stack2[head2].id+1; head2++; } ans=max(ans,i-l+1); } printf("%d",ans); return 0;}
2 0
- bzoj 2500: 幸福的道路 动态规划+单调栈
- bzoj 2500 幸福的道路 动态规划+单调栈
- BZOJ 2500 幸福的道路 树形DP+单调队列
- bzoj 2500 幸福的道路 dfs 单调队列
- 幸福的道路(race) ssl 2570 bzoj 2500 单调队列
- [BZOJ 2500]幸福的道路 树形dp+单调队列+二分答案
- bzoj 2500 幸福的道路 树上直径+set
- 【bzoj2500】幸福的道路 单调队列+树形dp
- 【bzoj2500】【幸福的道路】【树形dp+单调队列】
- 幸福的道路_bzoj2500_树形dp+单调队列
- noip2009 道路游戏 (单调队列优化动态规划)
- 幸福的道路
- 幸福的道路(race)
- BZOJ 1499 [NOI2005]瑰丽华尔兹 动态规划(+单调队列)
- BSOJ3068 BZOJ2500 noip模拟赛 幸福的道路 树的最长链+单调队列 或 RMQ
- 道路游戏 动态规划
- 【动态规划\单调队列】逃亡的准备
- 关于动态规划的单调队列优化
- java设计模式总结
- Android Studio Git的使用-基于GitLab
- 分隔List集合,按指定大小,将集合分成多个
- wemall doraemon中Android app商城系统工具集合类,包含各种程序中用到的静态方法
- Android平台下APP唤醒机制
- bzoj 2500: 幸福的道路 动态规划+单调栈
- 多种方式实现Sigmoid函数导数的仿真(含代码)
- 服务端与客户端存储形式之登录方式演变
- [leetcode]20. Valid Parentheses
- 微信jsapi开发教程之微信jsapi与java初步接入(第四课)
- Android 命名规范
- NDK开发的奇技淫巧(一)
- 快乐的实现单独页面横屏
- asp.net创建webapi