Topic: Given a tree, make a[i] for the longest chain from the first node I, find the longest interval in a[i], the difference between the maximum and minimum value of the interval does not exceed M
Reading the wrong questions kills people, brain destroys the dead
A[i] is apparently a tree-shaped DP
Consider a chain that starts from one point and can walk from a child node, or from a parent node.
So we dp two times, the first time to find out the longest chain from the child node, the second time to find out the longest chain from the parent node, two times to take Max is the answer
But direct DP can be problematic because the longest chain that goes from the parent node may be from its own subtree, so it will go heavy
Therefore, in addition to record the longest chain from the sub-node to record a second sub-node from the next chain, if the longest chain length is the same from the junior chain to go
The second question is to use a monotonous queue.
Time complexity O (n)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 1001001using namespace Std;struct abcd{int to,f,next;} Table[m<<1];int Head[m],tot;int N,m,ans;long Long f[m],g[m],h[m],a[m];//f represents the longest chain coming from a child node//g representing the junior chain coming from a child node// H represents the longest chain void Add (int x,int y,int z) coming from the parent node {Table[++tot].to=y;table[tot].f=z;table[tot].next=head[x];head[x]=tot;} void Tree_dp1 (int x) {int i;for (i=head[x];i;i=table[i].next) {TREE_DP1 (table[i].to); if (f[table[i].to]+table[i].f >F[X]) G[x]=f[x],f[x]=f[table[i].to]+table[i].f;else if (f[table[i].to]+table[i].f>g[x]) g[x]=f[table[i].to] +TABLE[I].F;}} void tree_dp2 (int x) {int I;a[x]=max (f[x],h[x]); for (I=head[x];i;i=table[i].next) {Long Long temp= (f[x]==f[table[i].to ]+table[i].f? G[X]: f[x]); Temp=max (Temp,h[x]); h[table[i].to]=temp+table[i].f; TREE_DP2 (table[i].to);}} void Monotonous_queue () {static int q_max[m],r_max,h_max;static int Q_min[m],r_min,h_min;int i,j;for (j=0,i=1;i<=n; i++) {{int *q=q_max,&r=r_max,&h=h_max;whiLe (r-h>=1 && a[i]>=a[q[r]) q[r--]=0;q[++r]=i;} {int *q=q_min,&r=r_min,&h=h_min;while (r-h>=1 && a[i]<=a[q[r]) q[r--]=0;q[++r]=i;} while (a[q_max[h_max+1]]-a[q_min[h_min+1]]>m) {++j;if (q_min[h_min+1]==j) q_min[++h_min]=0;if (q_max[h_max+1]==j ) q_max[++h_max]=0;} Ans=max (ANS,I-J);}} int main () {int i,x,y;cin>>n>>m;for (i=2;i<=n;i++) {scanf ("%d%d", &x,&y); ADD (x,i,y);} TREE_DP1 (1); TREE_DP2 (1); Monotonous_queue (); Cout<<ans<<endl;}
Bzoj 2500 Happy Road tree-shaped dp+ monotone queue