【bzoj2500】幸福的道路 【树形dp】【单调队列优化dp】
题目链接
强行拼题。。。
先是经典的树上最长路的树形dp,然后单调队列优化dp就好了。时间复杂度。
怎么树d,我之前好像写过。。。这里的T6就是。
代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=1000005;
int n,u,cnt,ans=1,f1,r1,f2,r2,head[N],q1[N*2],q2[N*2],to[N*2],nxt[N*2];
ll m,d,dd[N*2],f[N][3];
void adde(int u,int v,ll d){
to[++cnt]=v;
nxt[cnt]=head[u];
dd[cnt]=d;
head[u]=cnt;
}
void dfs1(int pre,int u){
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre){
dfs1(u,v);
if(f[v][0]+dd[i]>f[u][0]){
f[u][1]=f[u][0];
f[u][0]=f[v][0]+dd[i];
}else if(f[v][0]+dd[i]>f[u][1]){
f[u][1]=f[v][0]+dd[i];
}
}
}
f[u][2]=f[u][0];
}
void dfs2(int pre,int u,ll d){
f[u][2]=max(f[u][2],d);
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=pre){
if(f[v][0]+dd[i]==f[u][0]){
dfs2(u,v,max(d,f[u][1])+dd[i]);
}else{
dfs2(u,v,max(d,f[u][0])+dd[i]);
}
}
}
}
int main(){
scanf("%d%lld",&n,&m);
for(int i=2;i<=n;i++){
scanf("%d%lld",&u,&d);
adde(u,i,d);
adde(i,u,d);
}
dfs1(0,1);
dfs2(0,1,0);
q1[f1=r1=1]=1;
q2[f2=r2=1]=1;
for(int i=2,j=1;i<=n;i++){
while(f1<=r1&&q1[f1]<j){
f1++;
}
while(f2<=r2&&q2[f2]<j){
f2++;
}
while(f1<=r1&&f[q1[r1]][2]<f[i][2]){
r1--;
}
q1[++r1]=i;
while(f2<=r2&&f[q2[r2]][2]>f[i][2]){
r2--;
}
q2[++r2]=i;
while(f1<=r1&&f2<=r2&&f[q1[f1]][2]-f[q2[f2]][2]>m){
j++;
while(f1<=r1&&q1[f1]<j){
f1++;
}
while(f2<=r2&&q2[f2]<j){
f2++;
}
}
ans=max(ans,i-j+1);
}
printf("%d\n",ans);
return 0;
}