牛客多校訓練(第一場)H-Longest Path(點分治+李超樹)
阿新 • • 發佈:2019-01-22
題意:
一顆有邊權的樹,對於一條路徑(u,v),假設經過的邊權為,則該路徑權值cal(u,v)為,對每個點求
思路:
點分治,每次dfs出重心root到某個點u的以及最上面的邊權,然後不斷更新,路徑(u,v)的價值就是,我們正著掃一次,然後反著掃一次,就能處理出這些值。
現在問題就剩下一個問題了,如何維護這個最大值,因為是要維護兩個值,而且我們注意到這些都可以抽象為二次函式且開口都向上,這樣用李超樹就能很好地維護了,並且開口大小都相等,所以倆個線只有一個交點,就更好維護了,但是需要優化,因為同一子樹裡,最深的那個值必定最大,所以一個子樹維護一個函式就行了
錯誤及反思:
牛客機子有毒,如果程式碼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]);
}
}