bzoj 3672: [Noi2014]购票
2018-01-09 15:10
453 查看
Description
今年夏天,NOI在SZ市迎来了她30周岁的生日。来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会。全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的父亲用道路连接。为了方便起见,我们将全国的 n 个城市用 1 到 n 的整数编号。其中SZ市的编号为 1。对于除SZ市之外的任意一个城市 v,我们给出了它在这棵树上的父亲城市 fv 以及到父亲城市道路的长度 sv。
从城市 v 前往SZ市的方法为:选择城市 v 的一个祖先 a,支付购票的费用,乘坐交通工具到达 a。再选择城市 a 的一个祖先 b,支付费用并到达 b。以此类推,直至到达SZ市。
对于任意一个城市 v,我们会给出一个交通工具的距离限制 lv。对于城市 v 的祖先 a,只有当它们之间所有道路的总长度不超过 lv 时,从城市 v 才可以通过一次购票到达城市 a,否则不能通过一次购票到达。对于每个城市 v,我们还会给出两个非负整数 pv,qv 作为票价参数。若城市 v 到城市 a 所有道路的总长度为 d,那么从城市 v 到城市 a 购买的票价为 dpv+qv。
每个城市的OIer都希望自己到达SZ市时,用于购票的总资金最少。你的任务就是,告诉每个城市的OIer他们所花的最少资金是多少。
Solution
这题坑死我了正解:斜率优化DP
容易推出 \(f[i]=f[v]+(dis[i]-dis[v])*p[i]+q[i]\) \(v\)为某个祖先
化成斜率优化的形式:\(f[v]=dis[v]*p[i]+f[i]-q[i]-dis[i]*p[i]\)
所以相当于使用 \(k=p[i],b=f[i]-q[i]+dis[i]*p[i]\) 的直线去割若干个点 \((dis[v],f[v])\)
因为转移是在父子之间的,所以可以分治.
1.首先递归父亲所在块
2.用父亲所在的块更新所有儿子所在的块
3.递归处理所有的儿子
更新的方式大致是:
儿子按 \(dis[i]-l[i]\) 排序,把符合要求的点加入,维护凸包(然而大佬们都是半平面交),三分合适的斜率.
口胡完了,实现也比较简单
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=200005; int TT,head ,num=0,nxt[N<<1],to[N<<1];ll c[N<<1]; ll dis ,p ,q ,lim ,inf;int n,fa ;bool vis ; inline void link(int x,int y,ll z){ nxt[++num]=head[x];to[num]=y;c[num]=z;head[x]=num; } int sz ,son ={N},sum,rt; inline void getroot(int x,int last){ sz[x]=1;son[x]=0; for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(vis[u] || u==last)continue; getroot(u,x); sz[x]+=sz[u];son[x]=max(son[x],sz[u]); } son[x]=max(son[x],sum-sz[x]); if(son[x]<son[rt])rt=x; } inline void priwork(int x,int last){ for(int i=head[x];i;i=nxt[i]){ int u=to[i]; if(u==last)continue; dis[u]=dis[x]+c[i];fa[u]=x; priwork(u,x); } } int Q ,cnt=0,pre ,a ,tot=0,st ;ll f ; inline void bfs(int S){ int t=0;cnt=0; Q[++cnt]=S;pre[S]=fa[S]; while(t!=cnt){ int x=Q[++t]; for(int i=head[x];i;i=nxt[i]){ if(to[i]==pre[x] || vis[to[i]])continue; Q[++cnt]=to[i];pre[to[i]]=x; } } for(int i=1;i<=cnt;i++)pre[Q[i]]=0; } inline void dfs(int x,int root){ if(!x)return ; a[++tot]=x; if(x==root)return ; if(fa[x])dfs(fa[x],root); } inline bool comp(int i,int j){ if(dis[i]!=dis[j])return dis[i]>dis[j]; return f[i]<f[j]; } inline bool compdis(int i,int j){ return dis[i]-lim[i]>dis[j]-lim[j]; } inline void calc(int x,int root){ bfs(x); tot=0;dfs(fa[x],root); sort(a+1,a+tot+1,comp); sort(Q+1,Q+cnt+1,compdis); int top=0,r=1; for(int i=1;i<=cnt;i++){ int x=Q[i]; while(r<=tot && dis[x]-lim[x]<=dis[a[r]]){ while(top>=2 && (f[a[r]]-f[st[top]])/(dis[a[r]]-dis[st[top]])> (f[st[top]]-f[st[top-1]])/(dis[st[top]]-dis[st[top-1]]))top--; st[++top]=a[r++]; } int L=1,R=top,mid,ret=top,ml,mr; while(L<=R){ mid=(L+R)>>1; ml=(L+mid)>>1;mr=(mid+1+R)>>1; if(f[st[ml]]-dis[st[ml]]*p[x]<=f[st[mr]]-dis[st[mr]]*p[x])ret=ml,R=mr-1; else ret=mr,L=ml+1; } f[x]=min(f[x],f[st[ret]]+(dis[x]-dis[st[ret]])*p[x]+q[x]); } } inline void solve(int x,int root){ vis[x]=1; if(fa[x] && !vis[fa[x]]) rt=0,sum=sz[fa[x]],getroot(fa[x],x),solve(rt,root); calc(x,root); for(int i=head[x];i;i=nxt[i]){ if(vis[to[i]] || to[i]==fa[x])continue; rt=0;sum=sz[to[i]];getroot(to[i],x);solve(rt,x); } } void work() { int x;ll y; scanf("%d%d",&n,&TT); for(int i=2;i<=n;i++){ scanf("%d%lld%lld%lld%lld",&x,&y,&p[i],&q[i],&lim[i]); link(x,i,y);link(i,x,y); } memset(f,127/3,sizeof(f));f[1]=0;inf=f[0]; priwork(1,1);getroot(1,1); solve(1,1); for(int i=2;i<=n;i++)printf("%lld\n",f[i]); } int main() { freopen("pp.in","r",stdin); freopen("pp.out","w",stdout); work(); return 0; }
相关文章推荐
- 【BZOJ 3672】【UOJ #7】【NOI 2014】购票
- BZOJ 3672: [Noi2014]购票( 树链剖分 + 线段树 + 凸包 )
- 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治
- [Noi2014]购票 BZOJ3672 点分治+斜率优化+CDQ分治
- bzoj3672: [Noi2014]购票
- 【BZOJ3672】【UOJ7】【NOI2014】购票
- 【bzoj3672】[Noi2014]购票 斜率优化+树链剖分+线段树+凸包+三分
- BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化
- 【BZOJ 3672】 3672: [Noi2014]购票 (CDQ分治+点分治+斜率优化)**
- BZOJ 3672 [Noi2014]购票【点分+斜率优化
- bzoj3672 [Noi2014]购票(dp+斜率优化+点分治+cdq分治)
- BZOJ3672 [Noi2014]购票 【点分治 + 斜率优化】
- BZOJ 3672: [Noi2014]购票
- BZOJ 3672 NOI2014 购票
- bzoj 3672: [Noi2014]购票 树上cdq分治
- bzoj3672 [Noi2014]购票
- 【BZOJ 3672】[Noi2014]购票 树分治+斜率优化
- BZOJ 3672 NOI2014 购票 树的分治 NOI2014全AC达成!!!!
- bzoj 3672: [Noi2014]购票
- [BZOJ3672][NOI2014]购票 树分治斜率优化