题面传送门
这个一眼分数规划然后转化成树上长度在\([L,R]\)之间的最长路径问题。
这个东西可以长链剖分解决,就是像重链剖分一样用线段树维护,然后轻儿子暴力查找和加入即可。
注意不要忘了一条链的情况。
时间复杂度\(O(nlognlogw)\)
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define re register #define ll long long #define db double #define lb long db #define N 100000 #define K 50 #define mod 998244353 #define Mod 998244352 #define eps (1e-4) #define U unsigned int #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) #define d(x,y) (n*(x-1)+(y)) using namespace std; int n,m,k,x,y,z,Up,Low,len[N+5],son[N+5],id[N+5],idea;db l,r,mid,W[N+5],F[N+5<<2],Ans,now; struct yyy{int to,w,z;}; struct ljb{int head,h[N+5];yyy f[N+5<<1];I void add(int x,int y,int z){f[++head]=(yyy){y,z,h[x]};h[x]=head;}}s; I void build(int l=1,int r=n,int now=1){F[now]=-1e18;if(l==r) return;int m=l+r>>1;build(l,m,now<<1);build(m+1,r,now<<1|1);} I void insert(int x,db y,int l=1,int r=n,int now=1){F[now]=max(F[now],y);if(l==r)return;int m=l+r>>1;x<=m?insert(x,y,l,m,now<<1):insert(x,y,m+1,r,now<<1|1);} I db Query(int x,int y,int l=1,int r=n,int now=1){if(x<=l&&r<=y) return F[now];int m=l+r>>1;db Ans1=-1e18,Ans2=-1e18;x<=m&&(Ans1=Query(x,y,l,m,now<<1));y>m&&(Ans2=Query(x,y,m+1,r,now<<1|1));return max(Ans1,Ans2);} I void dfs1(int x,int last){yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(dfs1(tmp.to,x),len[son[x]]<len[tmp.to]&&(son[x]=tmp.to));len[x]=len[son[x]]+1;} I void dfs2(int x,int last){id[x]=++idea;if(!son[x]) return;dfs2(son[x],x);yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&tmp.to^son[x]&&(dfs2(tmp.to,x),0);} I void Make(int x,int last){yyy tmp;for(int i=s.h[x];i;i=tmp.z) tmp=s.f[i],tmp.to^last&&(W[tmp.to]=W[x]+tmp.w-mid,Make(tmp.to,x),0);} I void dfs(int x,int last){ yyy tmp;int i,j;insert(id[x],W[x]);if(!son[x]) return;dfs(son[x],x);for(int i=s.h[x];i;i=tmp.z){ tmp=s.f[i];if(tmp.to==last||tmp.to==son[x])continue;dfs(tmp.to,x);for(j=max(1,Low-len[x]+1);j<=min(len[tmp.to],Up);j++) now=Query(id[tmp.to]+j-1,id[tmp.to]+j-1)+Query(id[x]+max(Low-j,0),id[x]+min(Up-j,len[x]-1)),Ans=max(Ans,now-2*W[x]); for(j=1;j<=len[tmp.to];j++) insert(id[x]+j,Query(id[tmp.to]+j-1,id[tmp.to]+j-1)); }len[x]-1>=Low&&(now=Query(id[x]+Low,id[x]+min(Up,len[x]-1)),Ans=max(Ans,now-W[x])); } I int check(db mid){build();Ans=-1e18;Make(1,0);dfs(1,0);return Ans>=0;} int main(){ freopen("1.in","r",stdin); re int i;scanf("%d%d%d",&n,&Low,&Up);for(i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),s.add(x,y,z),s.add(y,x,z),r=max(r,z);dfs1(1,0);dfs2(1,0);l=0;r++;while(l+eps<r) mid=(l+r)/2,(check(mid)?l:r)=mid;printf("%.3lf\n",l); }