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;}