bzoj3672: [Noi2014]购票

来源:互联网 发布:大数据平台基础设施 编辑:程序博客网 时间:2024/05/16 12:50

为什么我这么慢!!!

这道题大概有两种思路,树分治和线段树。

树分治:使用类似cdq的方式,1:找重心,分裂,2:work(根所在的树)3:用重心到根的点的答案更新重心的子树,4:work(重心的子树)。更新的时候维护一个下凸壳,在下凸壳上二分即可。(我写了这个)

线段树:同样需要维护下凸壳,考虑在dfs时动态维护当前节点到根路径上的区间下凸壳,这个用线段树在每个节前维护一个支持回撤的单调栈,每次在栈上二分也是可以的。

时间复杂度O(nlog^2n)

#include<iostream>#include<cstdio>#include<algorithm>#define N 200005#define ll long long#define ld long doubleusing namespace std;ll n,fa[N],dep[N],sz[N],b[N],len[N],Mx[N],p[N],q[N];ll first[N],to[N],nxt[N],l,fl[N],lenth[N];ll a[N],m,dp[N],st[N];ll read(){ll x=0;char c=getchar();while(c<'0'||c>'9')c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return x;}bool cmp(ll x,ll y){return b[x]>b[y];}void link(ll x,ll y,ll z){to[++l]=y;lenth[l]=z;nxt[l]=first[x];first[x]=l;}void dfs(ll x){b[x]=max(0LL,dep[x]-len[x]);for (ll i=first[x];i;i=nxt[i]){dep[to[i]]=dep[x]+lenth[i];dfs(to[i]);}}void Get(ll x,ll y,ll &G){sz[x]=1;Mx[x]=0;for (ll i=first[x];i;i=nxt[i])if (!fl[i]){Get(to[i],y,G);sz[x]+=sz[to[i]];Mx[x]=max(Mx[x],sz[to[i]]);}Mx[x]=max(Mx[x],y-sz[x]);if (Mx[x]<=y/2) G=x;}void Dfs(ll x) {a[++m]=x;for (ll i=first[x];i;i=nxt[i])if (!fl[i])Dfs(to[i]);}bool pd(ll x,ll y,ll z){return (ld)(dp[z]-dp[x])/(dep[z]-dep[x])>(ld)(dp[z]-dp[y])/(dep[z]-dep[y]);}ll find(ll l,ll r,ll p){ll mid,ans=l;l++;while(l<=r){mid=l+r>>1;if ( (ld)(dp[st[mid-1]]-dp[st[mid]])/(dep[st[mid-1]]-dep[st[mid]])> p)ans=mid,l=mid+1;else r=mid-1;}return st[ans];}void work(ll x,ll y){if (y==1) return;ll G=0;Get(x,y,G);for (ll i=first[G];i;i=nxt[i])fl[i]=1;work(x,y-sz[G]+1);m=0;for (ll i=first[G];i;i=nxt[i])Dfs(to[i]);sort(a+1,a+m+1,cmp);ll r=1,tp=0;while(r<=m&&b[a[r]]>dep[G]) r++;for (ll i=G;i!=fa[x];i=fa[i]){if (!(tp&&dp[i]>=dp[st[tp]])){while(tp>=2&& pd(i,st[tp],st[tp-1]) ) tp--;st[++tp]=i;}for (;r<=m&&(b[a[r]]>dep[fa[i]]||i==x);r++){ll t=find(1,tp,p[a[r]]);t=dp[t]+(dep[a[r]]-dep[t])*p[a[r]]+q[a[r]];dp[a[r]]=min(dp[a[r]],t);}}for (ll i=first[G];i;i=nxt[i])work(to[i],sz[to[i]]);}int main(){n=read();read();dp[1]=0;for (ll i=2,o;i<=n;i++){fa[i]=read();o=read();p[i]=read();q[i]=read();len[i]=read();link(fa[i],i,o);dp[i]=1e18;}dfs(1);work(1,n);for (ll i=2;i<=n;i++)printf("%lld\n",dp[i]);}


0 0