POJ3162 Walking Race(树形DP+尺取法+单调队列)
2016-03-23 18:39
357 查看
题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长。
各个结点到其他结点的最远距离可以用树形DP解决,HDU2196。
而那个最长的连续子序列可以用单调队列求。。搞了挺久看了解法体会了下。。简单来说就是尺取法,用两个指针[i,j]表示区间,j不停+1往前移动,然后用两个单调队列分别同时更新区间最小值和最大值,再看两个队列队首的最值差是否大于m,是的话出队并调整i值,最后用j-i+1更新答案。
当然尺取法+RMQ也是OK的。
各个结点到其他结点的最远距离可以用树形DP解决,HDU2196。
而那个最长的连续子序列可以用单调队列求。。搞了挺久看了解法体会了下。。简单来说就是尺取法,用两个指针[i,j]表示区间,j不停+1往前移动,然后用两个单调队列分别同时更新区间最小值和最大值,再看两个队列队首的最值差是否大于m,是的话出队并调整i值,最后用j-i+1更新答案。
当然尺取法+RMQ也是OK的。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define INF (1LL<<60) #define MAXN 1000111 struct Edge{ int v,w,next; }edge[MAXN]; int NE,head[MAXN]; void addEdge(int u,int v,int w){ edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u]; head[u]=NE++; } int idx[MAXN]; long long d[3][MAXN]; void dp0(int u){ for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; dp0(v); if(d[0][u]<=d[0][v]+edge[i].w){ d[1][u]=d[0][u]; d[0][u]=d[0][v]+edge[i].w; idx[u]=v; }else if(d[1][u]<d[0][v]+edge[i].w){ d[1][u]=d[0][v]+edge[i].w; }else if(d[1][u]<d[1][v]+edge[i].w){ d[1][u]=d[1][v]+edge[i].w; } } } void dp1(int u){ for(int i=head[u]; i!=-1; i=edge[i].next){ int v=edge[i].v; if(idx[u]==v) d[2][v]=max(d[1][u],d[2][u])+edge[i].w; else d[2][v]=max(d[0][u],d[2][u])+edge[i].w; dp1(v); } } struct Que{ int que[MAXN],front,rear; bool isEmpty(){ return front==rear; } int getFront(){ return que[front]; } int getRear(){ return que[rear-1]; } void push(int a){ que[rear++]=a; } }mxq,mmq; int main(){ memset(head,-1,sizeof(head)); int n,m,a,b; scanf("%d%d",&n,&m); for(int i=2; i<=n; ++i){ scanf("%d%d",&a,&b); addEdge(a,i,b); } dp0(1); dp1(1); int res=0; for(int i=1,j=1; i<=n; ++i){ d[0][i]=max(d[0][i],d[2][i]); while(!mxq.isEmpty() && d[0][mxq.getRear()]<d[0][i]) --mxq.rear; mxq.push(i); while(!mmq.isEmpty() && d[0][mmq.getRear()]>d[0][i]) --mmq.rear; mmq.push(i); while(d[0][mxq.getFront()]-d[0][mmq.getFront()]>m){ if(mxq.getFront()<mmq.getFront()) j=mxq.getFront()+1,++mxq.front; else j=mmq.getFront()+1,++mmq.front; } res=max(res,i-j+1); } printf("%d",res); return 0; }
相关文章推荐
- sql联合索引效率问题
- 【面试问题】关于水平居中和垂直居中
- 完美配置Tomcat的HTTPS
- 设计模式(10)--组合模式
- 学习Discuz! X3.2记录:一个小提示,可以知道插件php文件语法出问题了
- 备忘录模式
- 第三周作业(三)WordCount
- JS 数组去重!!!
- [转]Linux 的多线程编程的高效开发经验
- 对计算机网络考研知识点归纳(不断更新中T)
- 自定义瀑布流式的标签列表
- 原型模式(Prototype)
- Android 常用的适配器总结
- iOS - nil、Nil、NULL、NSNull简单介绍
- linux:计算机概论
- HTML学习笔记
- POJ 1006 - Biorhythms (中国剩余定理)
- linux内核sk_buff的结构分析
- 对于结对编程的体会
- nodejs 在centos上安装笔记