1. 程式人生 > >牛客多校訓練(第一場)H-Longest Path(點分治+李超樹)

牛客多校訓練(第一場)H-Longest Path(點分治+李超樹)

題意:

        一顆有邊權的樹,對於一條路徑(u,v),假設經過的邊權為e1,e2,e3,...ef,則該路徑權值cal(u,v)為(e2e1)2+(e3e2)2+...+efef1)2,對每個點求fu=maxucal(u,v)

思路:

        點分治,每次dfs出重心root到某個點u的cal(root,u)以及最上面的邊權v,然後不斷更新,路徑(u,v)的價值就是

cal(u,root)+cal(v,root)+(v1v2)2,我們正著掃一次,然後反著掃一次,就能O(nlogn)處理出這些值。
        現在問題就剩下一個問題了,如何維護這個最大值,因為是要維護兩個值,而且我們注意到這些都可以抽象為二次函式且開口都向上,這樣用李超樹就能很好地維護了,並且開口大小都相等,所以倆個線只有一個交點,就更好維護了,但是需要優化,因為同一子樹裡,最深的那個值必定最大,所以一個子樹維護一個函式就行了

錯誤及反思:

牛客機子有毒,如果程式碼t了多交幾發就能A

程式碼:

#include<bits/stdc++.h>
#define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; const int N = 100100; struct EDGE{ int to,next; long long val; }e[N*2]; inline int read() { char ch = getchar(); int x = 0, f = 1; while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); } while
('0' <= ch && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } return x * f; } int first[N],n,tot,si[N],maxn[N],k; bool did[N],zaima[N]; long long ans[N],segk[N<<2],segd[N<<2],tmax; struct panshao{ long long val; int muqian; }; vector<panshao> v; long long Getval(long long x,long long k,long long d){return 1ll*(k-x)*(k-x)+1ll*d;} double Inter(long long k1,long long b1,long long k2,long long b2){return 1.0*(1.0*k2*k2-1.0*k1*k1+1.0*b2-1.0*b1)/(2.0*(1.0*k2-1.0*k1));} void Clear(int l,int r,int rt){ if(!zaima[rt]) return ; zaima[rt]=false; if(l==r) return ; int m=l+r>>1; if(zaima[rt<<1]) Clear(lson); if(zaima[rt<<1|1]) Clear(rson); } void update(long long k,long long d,int l,int r,int rt){ if(!zaima[rt]) segk[rt]=k,segd[rt]=d,zaima[rt]=true; else{ long long f1=Getval(l,k,d),f2=Getval(l,segk[rt],segd[rt]),f3=Getval(r,k,d),f4=Getval(r,segk[rt],segd[rt]); if(f1<=f2&&f3<=f4) return ; else if(f1>=f2&&f3>=f4) segk[rt]=k,segd[rt]=d; else{ int m=l+r>>1; double len=Inter(k,d,segk[rt],segd[rt]); if(f1>=f2){ if(len<=m) update(k,d,lson); else{ update(segk[rt],segd[rt],rson); segk[rt]=k; segd[rt]=d; } } else{ if(len>m)update(k,d,rson); else{ update(segk[rt],segd[rt],lson); segk[rt]=k; segd[rt]=d; } } } } } void query(int x,int l,int r,int rt){ if(zaima[rt]) tmax=max(tmax,Getval(x,segk[rt],segd[rt])); if(l==r) return ; int m=l+r>>1; if(m>=x) query(x,lson); else query(x,rson); } void addedge(int x,int y,long long z){ e[tot].to=y; e[tot].next=first[x]; e[tot].val=z; first[x]=tot++; e[tot].to=x; e[tot].next=first[y]; e[tot].val=z; first[y]=tot++; } void dfs_size(int now,int fa){ si[now]=1; maxn[now]=0; for(int i=first[now];i!=-1;i=e[i].next) if(e[i].to!=fa&&!did[e[i].to]){ dfs_size(e[i].to,now); si[now]+=si[e[i].to]; maxn[now]=max(maxn[now],si[e[i].to]); } } void dfs_root(int now,int fa,int& root,int& nu,int t){ int MA=max(maxn[now],si[t]-si[now]); if(MA<nu){ nu=MA; root=now; } for(int i=first[now];i!=-1;i=e[i].next) if(e[i].to!=fa&&!did[e[i].to]) dfs_root(e[i].to,now,root,nu,t); } void dfs2(int now,int fa,long long val,long long syg,long long ssg){ for(int i=first[now];i!=-1;i=e[i].next) if(e[i].to!=fa&&!did[e[i].to]) if(ssg==-1) dfs2(e[i].to,now,val,e[i].val,syg); else dfs2(e[i].to,now,val+1ll*(syg-ssg)*(syg-ssg),e[i].val,syg); if(ssg==-1) v.push_back({val,now}); else v.push_back({val+1ll*(syg-ssg)*(syg-ssg),now}); } void solve(int now){ int root,nu=1e9; dfs_size(now,-1); dfs_root(now,-1,root,nu,now); did[root]=true; vector<pair<int,long long> > vv; bool w=false; for(int i=first[root];i!=-1;i=e[i].next){ if(!did[e[i].to]){ vv.push_back({e[i].to,e[i].val}); v.clear(); dfs2(e[i].to,root,0,e[i].val,-1); if(w){ tmax=0; query(e[i].val,1,100000,1); for(int j=0;j<v.size();j++) ans[v[j].muqian]=max(ans[v[j].muqian],tmax+v[j].val); } long long maxx=0; for(int j=0;j<v.size();j++){ ans[root]=max(ans[root],v[j].val); maxx=max(maxx,v[j].val); } update(e[i].val,maxx,1,100000,1); w=true; } } w=false; Clear(1,100000,1); for(int i=(int)vv.size()-1;i>=0;i--){ v.clear(); dfs2(vv[i].first,root,0,vv[i].second,-1); if(w){ tmax=0; query(vv[i].second,1,100000,1); for(int j=0;j<v.size();j++) ans[v[j].muqian]=max(ans[v[j].muqian],tmax+v[j].val); } long long maxx=0; for(int j=0;j<v.size();j++) maxx=max(maxx,v[j].val); update(vv[i].second,maxx,1,100000,1); w=true; } Clear(1,100000,1); for(int i=first[root];i!=-1;i=e[i].next) if(!did[e[i].to]) solve(e[i].to); } void init(){ memset(did,false,sizeof(did)); memset(first,-1,sizeof(first)); memset(ans,0,sizeof(ans)); memset(zaima,false,sizeof(zaima)); tot=0; } int main(){ while(scanf("%d",&n)!=EOF){ init(); int w; for(int i=0,u,v;i<n-1;i++){ u=read(); v=read(); w=read(); addedge(u,v,w); } solve(1); for(int i=1;i<=n;i++) printf("%lld\n",ans[i]); } }