学一发长链剖分
原来以前在ATCODER上做的一题就是这个套路…
#include
#include
#include
using namespace std;
const int N=100010;
int n,U,D,cnt,dpt[N],d[N],G[N],son[N],fa[N];
struct edge{
int t,nx;
double w;
}E[N<<1];
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
inline void addedge(int x,int y,int w){
E[++cnt].t=y; E[cnt].nx=G[x]; E[cnt].w=w; G[x]=cnt;
E[++cnt].t=x; E[cnt].nx=G[y]; E[cnt].w=w; G[y]=cnt;
}
void dfs1(int x,int f){
dpt[x]=dpt[f]+1; fa[x]=f; d[x]=dpt[x];
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=f){
dfs1(E[i].t,x);
if(d[E[i].t]>d[son[x]]) son[x]=E[i].t;
d[x]=max(d[x],d[E[i].t]);
}
}
int p[N],t;
void dfs2(int x){
p[x]=++t;
if(son[x]) dfs2(son[x]);
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=fa[x] && E[i].t!=son[x]) dfs2(E[i].t);
}
double mx[N<<2];
void Build(int g,int l,int r){
mx[g]=-1e20;
if(l==r) return ;
int mid=l+r>>1;
Build(g<<1,l,mid); Build(g<<1|1,mid+1,r);
}
double cur,f[N];
void pfs(int x){
for(int i=G[x];i;i=E[i].nx)
if(E[i].t!=fa[x]){
f[E[i].t]=f[x]+E[i].w;
pfs(E[i].t);
}
}
double Query(int g,int l,int r,int L,int R){
if(l==L && r==R) return mx[g];
int mid=L+R>>1;
if(r<=mid) return Query(g<<1,l,r,L,mid);
if(l>mid) return Query(g<<1|1,l,r,mid+1,R);
return max(Query(g<<1,l,mid,L,mid),Query(g<<1|1,mid+1,r,mid+1,R));
}
void Modify(int g,int x,int L,int R,double y){
mx[g]=max(mx[g],y);
if(L==R) return ;
int mid=L+R>>1;
(x<=mid)?Modify(g<<1,x,L,mid,y):Modify(g<<1|1,x,mid+1,R,y);
}
void dp(int x){
Modify(1,p[x],1,n,f[x]);
if(son[x]) dp(son[x]);
for(int i=G[x],v;i;i=E[i].nx)
if(E[i].t!=son[x] && E[i].t!=fa[x]){
dp(v=E[i].t);
for(int j=1;j<=d[v]-dpt[x] && jif(D-j>d[x]-dpt[x]) break;
cur=max(cur,Query(1,p[v]+j-1,p[v]+j-1,1,n)+Query(1,max(p[x]+D-j,p[x]),min(p[x]+U-j,p[x]+d[x]-dpt[x]),1,n)-2*f[x]);
}
for(int j=1;j<=d[E[i].t]-dpt[x];j++)
Modify(1,p[x]+j,1,n,Query(1,p[v]+j-1,p[v]+j-1,1,n));
}
if(D<=d[x]-dpt[x]) cur=max(cur,Query(1,p[x]+D,min(p[x]+U,p[x]+d[x]-dpt[x]),1,n)-f[x]);
}
inline bool check(double x){
Build(1,1,n); cur=-1e20;
for(int i=1;i<=cnt;i++) E[i].w-=x;
pfs(1); dp(1);
for(int i=1;i<=cnt;i++) E[i].w+=x;
return cur>-1e-7;
}
int main(){
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n); read(D); read(U);
for(int i=1,x,y,w;i1,0); dfs2(1);
double L=0,R=1e6,mid;
int ttt=check(7.5);
while(R-L>1e-7) check(mid=(L+R)/2)?L=mid:R=mid;
printf("%.3lf\n",(L+R)/2);
return 0;
}