P4292 [WC2010]重建計劃
阿新 • • 發佈:2018-11-13
!= 計劃 我不知道 upd 一個 ext href 復雜 最長
傳送門
首先這玩意兒很明顯是分數規劃,二分一個答案\(mid\),邊權變為\(w_i-mid\),然後看看能不能找到一條路徑長度在\([L,R]\)之間,且邊權總和非負,這個可以轉化為求一條滿足條件的邊權最大的路徑
這個實際上可以用點分做,用單調隊列可以優化到\(O(nlog^2n)\),然而我不知道為什麽寫掛掉了所以這裏就不說了……
我們設\(f_{i,j}\)表示以\(i\)為根的子樹中,從\(i\)向下走\(j\)步的鏈最長是多少。轉移可以用長鏈剖分優化到均攤\(O(1)\)。查詢答案的話可以用線段樹,這樣的話復雜度就是\(O(nlog^2n)\)
然而不知道為什麽長鏈剖分跑得並沒有點分快
//minamoto #include<bits/stdc++.h> #define ll long long #define inf 0x3f3f3f3f using namespace std; #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) char buf[1<<21],*p1=buf,*p2=buf; int read(){ int res,f=1;char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } const int N=2e5+5,M=N<<2;const double eps=1e-4; int head[N],Next[N],ver[N],edge[N],tot; inline void add(int u,int v,int e){ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;} int dfn[N],dep[N],son[N],w[N],n,L,R,cnt; double val[N],f[N],ans,mid; #define ls (p<<1) #define rs (p<<1|1) double s[M]; inline void clear(){for(int i=0;i<M;++i)s[i]=-inf;} void update(int p,int l,int r,int x,double v){ if(l==r)return (void)(s[p]=max(s[p],v)); int mid=(l+r)>>1; x<=mid?update(ls,l,mid,x,v):update(rs,mid+1,r,x,v); s[p]=max(s[ls],s[rs]); } double query(int p,int l,int r,int ql,int qr){ if(ql<=l&&qr>=r)return s[p]; int mid=(l+r)>>1;double res=-inf; if(ql<=mid)res=max(res,query(ls,l,mid,ql,qr)); if(qr>mid)res=max(res,query(rs,mid+1,r,ql,qr)); return res; } void dfs(int u,int fa){ for(int i=head[u];i;i=Next[i]){ int v=ver[i];if(v==fa)continue;dfs(v,u); if(dep[v]>=dep[son[u]])son[u]=v,w[u]=edge[i]; if(dep[v]+1>dep[u])dep[u]=dep[v]+1; } } void dfs1(int u,int fa){ dfn[u]=++cnt;if(son[u])dfs1(son[u],u); for(int i=head[u];i;i=Next[i])if(ver[i]!=fa&&ver[i]!=son[u])dfs1(ver[i],u); } void split(int u,int fa){ int pu=dfn[u]; if(son[u])split(son[u],u),val[pu]=val[pu+1]+w[u]-mid; update(1,1,n,pu,f[pu]=-val[pu]); if(dep[u]>=L){ double tmp=query(1,1,n,pu+L,pu+min(dep[u],R)); ans=max(ans,tmp+val[pu]); } for(int i=head[u];i;i=Next[i]){ int v=ver[i],pv=dfn[v];if(v==fa||v==son[u])continue; split(v,u); for(int j=0;j<=dep[v];++j){ int l=pu+max(0,L-j-1),r=pu+min(dep[u],R-j-1); double tmp=query(1,1,n,l,r); ans=max(ans,tmp+val[pv]+val[pu]+f[pv+j]+edge[i]-mid); } for(int j=0;j<=dep[v];++j){ double tmp=val[pv]+f[pv+j]+edge[i]-mid-val[pu]; if(tmp>f[pu+j+1])update(1,1,n,pu+j+1,f[pu+j+1]=tmp); } } } inline bool check(){ clear(); ans=-inf,split(1,0);return ans>=eps; } int main(){ // freopen("testdata.in","r",stdin); n=read(),L=read(),R=read(); for(int i=1,u,v,e;i<n;++i)u=read(),v=read(),e=read(),add(u,v,e),add(v,u,e); dfs(1,0),dfs1(1,0); double l=0,r=1e6; while(r-l>eps){ mid=(l+r)/2; check()?l=mid:r=mid; } printf("%.3lf\n",l);return 0; }
P4292 [WC2010]重建計劃