CF1000G Two-Paths&BSOJ6376【11.05模擬】草莓
阿新 • • 發佈:2021-08-20
前言
這個題還有個加強版:BSOJ6376【11.05模擬】草莓
大概是人均場切了。
題目
分析
首先這個路徑一定是一條鏈加上若干迴路的路徑。
每次 \(x\) 到 \(y\) 的途中都可以進入子樹進行獲取貢獻,為了儘可能大,我們可以先 \(dp\) 出每一個點到子樹再回來可以得到的最大貢獻。
以及每一個點到父親再回來可以得到的最大貢獻。
再處理每一個點對父親的 \(dp\) 值的貢獻,那麼每次詢問就變成了詢問路徑和,使用樹剖維護即可。
對於加強版就是還要考慮來回的路徑值不同,這個可以字首和一下解決。
程式碼
#include<bits/stdc++.h> using namespace std; template <typename T> inline void read(T &x){ x=0;char ch=getchar();bool f=false; while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();} while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();} x=f?-x:x; return ; } template <typename T> inline void write(T x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10^48); return ; } const int N=5e5+5; #define ll long long int n,a[N],q,idx; int head[N],to[N<<1],val1[N<<1],val2[N<<1],nex[N<<1],fa[N][20],dep[N]; inline void add(int u,int v,int w1,int w2){ nex[++idx]=head[u]; to[idx]=v; head[u]=idx; val1[idx]=w1; val2[idx]=w2; return ; } ll dp[N],dp1[N],dpp[N],c[N],costd[N],costu[N],c1[N],num[N]; void dfs(int x,int f,int id){ fa[x][0]=f; costd[x]=costd[f]+val1[id];costu[x]=costu[f]+val2[id]; num[x]=num[f]+a[x];dep[x]=dep[f]+1; for(int i=1;i<20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; dp[x]+=a[x]; for(int i=head[x];i;i=nex[i]){ int y=to[i]; if(y==f) continue; dfs(y,x,i); dp[x]+=c[y]; } c[x]=max(0ll,dp[x]-val1[id]-val2[id]); return ; } void dfs1(int x,int f,int id){ c1[x]=c1[f]+c[x];dpp[x]=dpp[f]+dp[x]; dp1[x]=max(dp1[f]+dp[f]-c[x]-val1[id]-val2[id],0ll); for(int i=head[x];i;i=nex[i]){ int y=to[i]; if(y==f) continue; dfs1(y,x,i); } // cout<<x<<" costd:"<<costd[x]<<" costu:"<<costu[x]<<" num:"<<num[x]<<" c:"<<c[x]<<" dp:"<<dp[x]<<" dp1:"<<dp1[x]<<" dpp:"<<dpp[x]<<" c1:"<<c1[x]<<endl; return; } inline int Getlca(int u,int v){ if(u==v) return u; if(dep[u]<dep[v]) swap(u,v); for(int i=19;i>=0;i--) if(dep[fa[u][i]]>=dep[v]) u=fa[u][i]; if(u==v) return u; for(int i=19;i>=0;i--) if(fa[u][i]!=fa[v][i]) u=fa[u][i],v=fa[v][i]; return fa[u][0]; } inline int Jump(int x,int lca){ for(int i=19;i>=0;i--) if(dep[fa[x][i]]>dep[lca]) x=fa[x][i]; return x; } signed main(){ // freopen("strawberry.in","r",stdin); // freopen("strawberry.out","w",stdout); read(n);read(q); for(int i=1;i<=n;i++) read(a[i]); for(int i=1;i<n;i++){ int u,v,w1,w2; read(u),read(v),read(w1),w2=w1; add(u,v,w1,w2); add(v,u,w2,w1); } dfs(1,0,0);c[1]=0; dfs1(1,0,0); while(q--){ int x,y; read(x),read(y); int lca=Getlca(x,y),ls=Jump(x,lca),rs=Jump(y,lca); // cout<<"LCA:"<<lca<<" ls:"<<ls<<" rs:"<<rs<<endl; if(x==lca) ls=0; if(y==lca) rs=0; ll Ans=0; if(x==y) Ans=dp[x]+dp1[x]; else Ans=dpp[x]+dpp[y]-2*dpp[lca]+dp[lca]+dp1[lca]-(c1[x]+c1[y]-c1[lca]*2)-costu[x]+costu[lca]-costd[y]+costd[lca]; // else Ans=dp[lca]+dp1[lca]-c[ls]-c[rs]-costu[x]+costu[lca]-costd[y]+costd[lca]+num[x]+num[y]-2*num[lca]; write(Ans),putchar('\n'); } return 0; }