传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3672
我写的是nlog^3n的链剖凸包,题解有很多,扔一发代码
Code:
#include<cstdio> #include<iostream> #include<algorithm> #include<vector> #include<queue> #include<cctype> typedef long long LL; const int maxn=2e5+5; using namespace std; int DEB; LL getint(){ LL res=0;char c=getchar(); while(!isdigit(c))c=getchar(); while(isdigit(c))res=res*10+c-'0',c=getchar(); return res; } struct point{ LL x,y; point(LL _x=0,LL _y=0):x(_x),y(_y){} double operator*(point oth)const{return (double)x*oth.y-(double)y*oth.x;} LL operator^(point oth)const{return (LL)x*oth.x+(LL)y*oth.y;} point operator-(point oth)const{return point(x-oth.x,y-oth.y);} point operator+(point oth)const{return point(x+oth.x,y+oth.y);} bool operator<(point oth)const{return x<oth.x||(x==oth.x&&y<oth.y);} void print(){printf("%d %d\n",int(x),int(y));} }tmp[maxn]; int tmpsize,n,T,siz[maxn],son[maxn],dep[maxn],top[maxn],w[maxn],rw[maxn],fa[maxn],z,dfn[maxn]; LL d[maxn],p[maxn],q[maxn],l[maxn],dp[maxn]; vector<int>G[maxn]; void dfs(int u){ siz[u]=1;dfn[++dfn[0]]=u; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]){ fa[v]=u;dep[v]=dep[u]+1;d[v]+=d[u]; dfs(v); siz[u]+=siz[v]; if(siz[son[u]]<siz[v])son[u]=v; } } } void buiLL(int u,int tp){ w[u]=++z;rw[z]=u;top[u]=tp; if(son[u])buiLL(son[u],tp); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]&&v!=son[u])buiLL(v,v); } } struct CH{ point *ch; int size; void init(int l,int r){ tmpsize=size=0; for(int i=l;i<=r;i++)tmp[++tmpsize]=point(d[rw[i]],dp[rw[i]]); sort(tmp+1,tmp+1+tmpsize); ch=new point[tmpsize+5]; for(int i=1;i<=tmpsize;i++){ while(size>1&&(tmp[i]-ch[size])*(ch[size]-ch[size-1])>=-1e-20)size--; ch[++size]=tmp[i]; } } LL qmin(point p){ int l=1,r=size; LL ans=min((ch[l]^p),(ch[r]^p)); while(r-l>2){ int mid1=l+(r-l)/3; int mid2=r-(r-l)/3; if((ch[mid1]^p)<=(ch[mid2]^p)) r=mid2; else l=mid1; } for(int i=l;i<=r;i++)ans=min(ans,(LL)(ch[i]^p)); return ans; } }; int findrt(int u){ LL lim=d[u]-l[u]; for(;u&&d[top[u]]>=lim;){ u=top[u]; if(d[fa[u]]>=lim)u=fa[u];else break; } if(!u)return 1; int l=w[u],r=w[top[u]]; if(l>r)swap(l,r); while(l<r){ int mid=(l+r)>>1; if(d[rw[mid]]<lim) l=mid+1; else r=mid; }return rw[l]; } bool bud[maxn<<2]; CH t[maxn<<2]; LL Qmin(int i,int l,int r,int l0,int r0,point p){ if(l0>r0)swap(l0,r0); if(l0<=l&&r0>=r){ if(bud[i])return t[i].qmin(p); bud[i]=1;t[i].init(l,r); return t[i].qmin(p); }int mid=(l+r)>>1;LL ans=1LL<<61; if(l0<=mid)ans=min(ans,Qmin(i<<1,l,mid,l0,r0,p)); if(r0>mid)ans=min(ans,Qmin(i<<1|1,mid+1,r,l0,r0,p)); return ans; } int main(){ n=getint();T=getint(); for(int i=2;i<=n;i++){ fa[i]=getint(),d[i]=getint(),p[i]=getint(),q[i]=getint(),l[i]=getint(); G[i].push_back(fa[i]);G[fa[i]].push_back(i); }if(T==0||T==2){ queue<int>q; q.push(1); while(!q.empty()){ int u=q.front();q.pop(); dfn[++dfn[0]]=u;w[u]=++z;rw[z]=u;top[u]=1; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v!=fa[u]){ q.push(v); d[v]+=d[u];fa[v]=u; dep[v]=dep[u]+1; son[u]=v; } } } }else dfs(1),buiLL(1,1); for(int i=2;i<=dfn[0];i++){ DEB=dfn[i]; dp[dfn[i]]=1LL<<61;int u=fa[dfn[i]],v=findrt(dfn[i]); for(;top[u]!=top[v];u=fa[top[u]]) dp[dfn[i]]=min(dp[dfn[i]],Qmin(1,1,n,w[u],w[top[u]],point(-p[dfn[i]],1))); dp[dfn[i]]=min(dp[dfn[i]],Qmin(1,1,n,w[u],w[v],point(-p[dfn[i]],1))); dp[dfn[i]]+=p[dfn[i]]*d[dfn[i]]+q[dfn[i]]; } for(int i=2;i<=n;i++)printf("%lld\n",dp[i]); return 0; }