Poj 3162 Walking Race (monotonous queue or line segment tree plus tree DP)

Source: Internet
Author: User

Question: give you a tree with N nodes. The edge of the tree is the weight value. You need to find the maximum distance between each node on the tree and other points. Find the longest segment from node 1 to the maximum node N value so that the node with the maximum and minimum values in this segment is less than or equal to M.

There are two solutions to the first problem. The first simple method is that the biggest value in the distance between each point and other points must be one of the distance between the two endpoints of the tree's diameter (the inverse method is easy to obtain ). At the same time of finding out the diameter of the tree, we can process the distance from each node to the two endpoints of the tree diameter. The second method is tree-based DP, Which is used twice for DFS. The first DFS finds the maximum distance to vertex I in the subtree where vertex I is the root node. However, the maximum distance we require may also be in the branch of the parent node, so we use the second DFS to process it. For details, refer to the code.

There are also two methods for the second problem: one is the line segment tree, which can be scanned once; the other is the monotonous queue, which maintains a monotonic increasing queue and a monotonic decreasing queue, I think it's clever.

1. Tree DP plus line segment tree

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;#define LL(x) (x<<1)#define RR(x) (x<<1|1)#define INF ((LL)1<<60)#define MID(a,b) (a+((b-a)>>1))const int N=1e6+5;struct Edge{int v,wei,pre;Edge(){}Edge(int a,int b,int c){v=a;pre=b;wei=c;}}edge[N*2];struct node{int lft,rht;LL mi,mx;int mid(){return MID(lft,rht);}};int head[N],tot;LL f1[N],f2[N];int g1[N],g2[N];void iswap(int u){if(f1[u]<f2[u]){swap(f1[u],f2[u]);swap(g1[u],g2[u]);}}void addEdge(int u,int v,int wei){edge[tot]=Edge(v,head[u],wei);head[u]=tot++;}void dfs_1(int u,int fa){f1[u]=f2[u]=0;for(int i=head[u];i!=-1;i=edge[i].pre){int v=edge[i].v,wei=edge[i].wei;if(v==fa) continue;dfs_1(v,u);if(f2[u]<f1[v]+wei){f2[u]=f1[v]+wei;g2[u]=v;iswap(u);}}}void dfs_2(int u,int fa){for(int i=head[u];i!=-1;i=edge[i].pre){int v=edge[i].v,wei=edge[i].wei;if(v==fa) continue;if(g1[u]==v){if(f2[v]<f2[u]+wei){f2[v]=f2[u]+wei;g2[v]=u;iswap(v);}}else {if(f2[v]<f1[u]+wei);{f2[v]=f1[u]+wei;g2[v]=u;iswap(v);}}dfs_2(v,u);}}struct Segtree{node tree[N*4];void build(int lft,int rht,int ind){tree[ind].lft=lft;tree[ind].rht=rht;tree[ind].mi=INF;tree[ind].mx=-INF;if(lft==rht) tree[ind].mi=tree[ind].mx=f1[lft];else {int mid=tree[ind].mid();build(lft,mid,LL(ind));build(mid+1,rht,RR(ind));tree[ind].mi=min(tree[LL(ind)].mi,tree[RR(ind)].mi);tree[ind].mx=max(tree[LL(ind)].mx,tree[RR(ind)].mx);}}void query(int st,int ed,int ind,LL &mi,LL &mx){int lft=tree[ind].lft,rht=tree[ind].rht;if(st<=lft&&rht<=ed) {mi=tree[ind].mi,mx=tree[ind].mx;return ;}else {int mid=tree[ind].mid();LL mi1=INF,mi2=INF,mx1=-INF,mx2=-INF;if(st<=mid) query(st,ed,LL(ind),mi1,mx1);if(ed>mid) query(st,ed,RR(ind),mi2,mx2);mi=min(mi1,mi2); mx=max(mx1,mx2);return ;}}}seg;int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF){tot=0;memset(head,-1,sizeof(head));for(int i=2;i<=n;i++){int x,y;scanf("%d%d",&x,&y);addEdge(i,x,y);addEdge(x,i,y);}dfs_1(1,-1); dfs_2(1,-1);int st=1,ed=1,res=0;LL mi,mx;seg.build(1,n,1);while(ed<=n){seg.query(st,ed,1,mi,mx);if(mx-mi<=m) {res=max(res,ed-st+1);ed++; }while(mx-mi>m){st++;seg.query(st,ed,1,mi,mx);}}printf("%d\n",res);}return 0;}

2. DFS and monotonous queue

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int N=1e6+5;struct Edge{int v,wei,pre;Edge(){}Edge(int a,int b,int c){v=a;pre=b;wei=c;}}edge[N*2];int head[N],tot,n,m;int dx[N],dy[N],d[N];int qmin[N],qmax[N];void addEdge(int u,int v,int wei){edge[tot]=Edge(v,head[u],wei);head[u]=tot++;}void dfs(int u,int fa,int dis,int *d){for(int i=head[u];i!=-1;i=edge[i].pre){int v=edge[i].v,wei=edge[i].wei;if(v!=fa) dfs(v,u,d[v]=dis+wei,d);}}void solve(){int ans=0,i,j,front1,front2,rear1,rear2;front1=rear1=0;front2=rear2=0;for(i=1,j=1;j<=n;j++){while(rear1>front1&&d[qmax[rear1-1]]<=d[j]) rear1--;qmax[rear1++]=j;while(rear2>front2&&d[qmin[rear2-1]]>=d[j]) rear2--;qmin[rear2++]=j;if(d[qmax[front1]]-d[qmin[front2]]>m){ans=max(ans,j-i);while(d[qmax[front1]]-d[qmin[front2]]>m){i=min(qmax[front1],qmin[front2])+1;while(rear1>front1&&qmax[front1]<i) front1++;while(rear2>front2&&qmin[front2]<i) front2++;}}}ans=max(ans,j-i);printf("%d\n",ans);}int main(){while(scanf("%d%d",&n,&m)!=EOF){tot=0;memset(head,-1,sizeof(head));int x,y,i;for(int i=2;i<=n;i++){scanf("%d%d",&x,&y);addEdge(i,x,y);addEdge(x,i,y);}dfs(1,0,d[1]=0,d);for(x=1,i=2;i<=n;i++)if(d[i]>d[x]) x=i;dfs(x,0,dx[x]=0,dx);for(y=1,i=2;i<=n;i++)if(dx[i]>dx[y]) y=i;dfs(y,0,dy[y]=0,dy);for(int i=1;i<=n;i++) d[i]=max(dx[i],dy[i]);solve();}return 0;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.