POJ 3162 Walking Race 树的直径+线段树
2017-10-26 21:03
246 查看
题目链接
http://poj.org/problem?id=3162题意
给定一颗含n个结点的树,求每个点能走到的最远距离,挑选连续的k天 最长与最短之差不超过m,求最大k思路
先求树的直径,然后线段树维护#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<vector> #include<string> #include<queue> #include<stack> #include<math.h> #include<set> #include<map> #define ll long long using namespace std; const int INF = ( 2e9 ) + 2; const ll maxn = 1e6+10; struct edge { int v,w,next; } e[maxn*2]; struct node { int Max,Min; int l,r; }t[maxn*4]; int head[maxn]; int tot; int d[2][maxn],Max[maxn]; bool vis[maxn]; int n,m; void build(int root,int l,int r) { t[root].l=l; t[root].r=r; if(l==r) { t[root].Max=t[root].Min=Max[l]; return; } int mid=(l+r)>>1; build(2*root,l,mid); build(2*root+1,mid+1,r); t[root].Max=max(t[root*2].Max,t[root*2+1].Max); t[root].Min=min(t[root*2].Min,t[root*2+1].Min); } int query(int root,int ql,int qr,bool mode) { int l=t[root].l,r=t[root].r; if(l>=ql&&r<=qr) { if(mode)return t[root].Max; else return t[root].Min; } if(l>qr||r<ql)return 0; int mid = (l+r)>>1; if(qr<=mid) return query(2*root,ql,qr,mode); else if(ql>mid) return query(2*root+1,ql,qr,mode); else { if(mode) return max(query(2*root,ql,qr,mode),query(2*root+1,ql,qr,mode)); else return min(query(2*root,ql,qr,mode),query(2*root+1,ql,qr,mode)); } } void init() { memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); tot=0; d[0][1]=0; } void add(int u,int v,int w) { e[tot].v=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot++; } // 连续的k天 最长与最短之差不超过m void dfs(int u,int *d) { vis[u]=true; for(int i=head[u]; i!=-1; i=e[i].next) { int v=e[i].v,w=e[i].w; if(vis[v])continue; d[v]=d[u]+w; dfs(v,d); } } int solve() { dfs(1,d[0]); int mx=-INF,pos; memset(vis,0,sizeof(vis)); for(int i=1; i<=n; i++) if(mx<d[0][i]) { mx=d[0][i]; pos=i; } d[0][pos]=0; memset(vis,0,sizeof(vis)); dfs(pos,d[0]); mx=-INF; for(int i=1;i<=n;i++) if(mx<d[0][i]) { mx=d[0][i]; pos=i; } d[1][pos]=0; memset(vis,0,sizeof(vis)); dfs(pos,d[1]); for(int i=1;i<=n;i++) Max[i]=max(d[0][i],d[1][i]); build(1,1,n); int i=1,j=1; int ans=-INF; for(;j<=n;j++) { while(query(1,i,j,1)-query(1,i,j,0)>m)i++; ans=max(ans,j-i+1); } return ans; } int main() { int u,v,w; while(~scanf("%d%d",&n,&m)) { init(); for(int i=2; i<=n; i++) { scanf("%d%d",&v,&w); add(i,v,w); add(v,i,w); } printf("%d\n",solve()); } }
相关文章推荐
- POJ 3162 Walking Race(树的直径+单调队列)
- POJ 3162 Walking Race (DFS + 线段树)
- POJ 3162 Walking Race (DFS + 线段树)
- POJ - 3162 Walking Race 【树上最远距离 + 线段树处理区间最值 + 尺取法 】
- 【树形DP】Poj 3162 Walking Race (DP_树形DP(线段树))
- POJ 3162 Walking Race (树的直径,单调队列)
- POJ 3162 Walking Race 树的直径+单调队列(其实暴力也可以>_<)
- POJ 3162 Walking Race(单调队列或线段树加树型DP)
- POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
- POJ 3162 Walking Race 树的直径加单调队列
- POJ 3162 Walking Race TreeDP+双单调队列 ★
- POJ3162 Walking Race(树形DP+尺取法+单调队列)
- POJ 3162 Walking Race 树形DP
- poj 3162 Walking Race (dfs+尺取法单调队列)★
- poj 3162 线段树 hdu 4123 bfs + RMQ预处理
- 【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
- POJ 3162 Walking Race(树形DP+单调队列)
- poj 3162 Walking Race
- POJ 3162 Walking Race (单调队列)@
- poj 3162 walking race 树形dp 求符合条件区间