BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化

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他们所花的最少资金是多少。

Input

第 1 行包含2个非负整数 n,t,分别表示城市的个数和数据类型(其意义将在后面提到)。输入文件的第 2 到 n 行,每行描述一个除SZ之外的城市。其中第 v 行包含 5 个非负整数 f_v,s_v,p_v,q_v,l_v,分别表示城市 v 的父亲城市,它到父亲城市道路的长度,票价的两个参数和距离限制。请注意:输入不包含编号为 1 的SZ市,第 2 行到第 n 行分别描述的是城市 2 到城市 n。

Output

输出包含 n-1 行,每行包含一个整数。其中第 v 行表示从城市 v+1 出发,到达SZ市最少的购票费用。同样请注意:输出不包含编号为 1 的SZ市。

Sample Input

7 3
1 2 20 0 3
1 5 10 100 5
2 4 10 10 10
2 9 1 100 10
3 5 20 100 10
4 4 20 0 10

Sample Output

40
150
70
149
300
150

$O(n^2)$DP:f[x]=f[p]+(dep[x]-dep[p])*P[x]+Q[x]  (dep[x]-dep[p]<=L[x])
如果是在序列上可以用斜率优化+二分或CDQ分治的方法解决。
但是这是一棵树。
考虑继续使用CDQ分治,假设当前solve的是x这棵子树,每次找到一个分治点p,从x中把p的子树抠掉。
先处理剩下的,然后计算x到p链上的点对p的子树的影响,然后递归p的子树。
然后这个分治点肯定要使得递归的两部分大小差不多大,需要每次求一下中心。
考虑x到p的链上的点对p的子树的影响怎么计算。
链上的点对dep升序,子树内的点按dep[x]-L[x]降序,这样决策点那边指针单调。
每次二分一下斜率就做完了。
细节还是有一些的,不过重要的还是怎么想到这种分治做法的。
 
代码:
  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <cstdlib>
  5. using namespace std;
  6. typedef long long ll;
  7. #define N 200050
  8. typedef double f2;
  9. int head[N],to[N],nxt[N],fa[N],n,cnt,mx[N],tot,root,siz[N],S[N],top,vis[N];
  10. ll val[N],dep[N],P[N],Q[N],L[N],f[N];
  11. int a[N],b[N],la,lb;
  12. inline void add(int u,int v,ll w) {
  13. to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
  14. }
  15. bool cmp1(const int &x,const int &y) {
  16. return dep[x]-L[x]>dep[y]-L[y];
  17. }
  18. f2 K(int i,int j) {
  19. return (f2(f[i]-f[j]))/(dep[i]-dep[j]);
  20. }
  21. void dfs(int x) {
  22. int i; siz[x]=1;
  23. for(i=head[x];i;i=nxt[i]) {
  24. dep[to[i]]=dep[x]+val[i];
  25. dfs(to[i]);
  26. siz[x]+=siz[to[i]];
  27. }
  28. }
  29. void get_root(int x) {
  30. int i;
  31. siz[x]=1; mx[x]=0;
  32. for(i=head[x];i;i=nxt[i]) if(!vis[to[i]]) {
  33. get_root(to[i]);
  34. siz[x]+=siz[to[i]];
  35. mx[x]=max(mx[x],siz[to[i]]);
  36. }
  37. mx[x]=max(mx[x],tot-siz[x]);
  38. if(mx[root]>mx[x]) root=x;
  39. }
  40. void diu1(int x,int y) {
  41. int p;
  42. for(p=x;p!=fa[y];p=fa[p]) a[++la]=p;
  43. }
  44. void diu2(int x) {
  45. int i; b[++lb]=x;
  46. for(i=head[x];i;i=nxt[i]) if(!vis[to[i]]) {
  47. diu2(to[i]);
  48. }
  49. }
  50. void solve(int x) {
  51. tot=siz[x]; root=0; get_root(x); int rt=root; vis[rt]=1;
  52. //printf("%d %d\n",x,rt);
  53. if(x!=rt) siz[x]-=siz[rt],solve(x);
  54. la=lb=0;
  55. int i,j;
  56. diu1(rt,x);
  57. for(i=head[rt];i;i=nxt[i]) if(!vis[to[i]]) {
  58. diu2(to[i]);
  59. }//printf("%d %d\n",la,lb);
  60. for(i=2;i<=la;i++) if(dep[rt]-dep[a[i]]<=L[rt]) f[rt]=min(f[rt],f[a[i]]+(dep[rt]-dep[a[i]])*P[rt]+Q[rt]);
  61.  
  62. sort(b+1,b+lb+1,cmp1);
  63.  
  64. top=0,S[0]=0;
  65. for(j=1,i=1;i<=lb;i++) {
  66. int u=b[i];
  67. while(j<=la&&dep[u]-dep[a[j]]<=L[u]) {
  68. while(top>1&&K(S[top],a[j])>K(S[top-1],S[top])) top--;
  69. S[++top]=a[j++];
  70. }
  71. if(!top) continue;
  72. if(top==1) f[u]=min(f[u],f[S[1]]+(dep[u]-dep[S[1]])*P[u]+Q[u]);
  73. else {
  74. int l=1,r=top;
  75. while(l<r) {
  76. int mid=(l+r)>>1;
  77. if(P[u]>K(S[mid],S[mid+1])) r=mid;
  78. else l=mid+1;
  79. }
  80. f[u]=min(f[u],f[S[l]]+(dep[u]-dep[S[l]])*P[u]+Q[u]);
  81. }
  82. }
  83.  
  84. for(i=head[rt];i;i=nxt[i]) if(!vis[to[i]]) {
  85. solve(to[i]);
  86. }
  87. }
  88. int main() {
  89. mx[0]=1<<30;
  90. scanf("%d%*d",&n);
  91. int i;
  92. ll x;
  93. for(i=2;i<=n;i++) {
  94. scanf("%d%lld%lld%lld%lld",&fa[i],&x,&P[i],&Q[i],&L[i]); add(fa[i],i,x);
  95. }
  96. memset(f,0x3f,sizeof(f));
  97. f[1]=0;
  98. dfs(1);
  99. solve(1);
  100. for(i=2;i<=n;i++) printf("%lld\n",f[i]);
  101. }

BZOJ_3672_ [Noi2014]购票_CDQ分治+斜率优化的更多相关文章

  1. 【BZOJ3672】[Noi2014]购票 树分治+斜率优化

    [BZOJ3672][Noi2014]购票 Description  今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会.       ...

  2. UOJ#7. 【NOI2014】购票 点分治 斜率优化 凸包 二分

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ7.html 题解 这题是Unknown的弱化版. 如果这个问题出在序列上,那么显然可以CDQ分治 + 斜率 ...

  3. 【BZOJ-3672】购票 树分治 + 斜率优化DP

    3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 1177  Solved: 562[Submit][Status][ ...

  4. [NOI2014]购票 「树上斜率优化」

    首先易得方程,且经过变换有 $$\begin{aligned} f_i &= \min\limits_{dist_i - lim_i \le dist_j} \{f_j + (dist_i - ...

  5. BZOJ3672 [Noi2014]购票 【点分治 + 斜率优化】

    题目链接 BZOJ3672 题解 如果暂时不管\(l[i]\)的限制,并假使这是一条链 设\(f[i]\)表示\(i\)节点的最优答案,我们容易得到\(dp\)方程 \[f[i] = min\{f[j ...

  6. 【uoj#244】[UER #7]短路 CDQ分治+斜率优化dp

    题目描述 给出 $(2n+1)\times (2n+1)$ 个点,点 $(i,j)$ 的权值为 $a[max(|i-n-1|,|j-n-1|)]$ ,找一条从 $(1,1)$ 走到 $(2n+1,2n ...

  7. BZOJ_1492_[NOI2007]货币兑换Cash_CDQ分治+斜率优化

    BZOJ_1492_[NOI2007]货币兑换Cash_CDQ分治+斜率优化 Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券 ...

  8. BZOJ1492:[NOI2007]货币兑换 (CDQ分治+斜率优化DP | splay动态维护凸包)

    BZOJ1492:[NOI2007]货币兑换 题目传送门 [问题描述] 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和B纪念券(以下简称B券).每个持有金券的 ...

  9. [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化)

    [BZOJ1492] [NOI2007] 货币兑换Cash(cdq分治+斜率优化) 题面 分析 dp方程推导 显然,必然存在一种最优的买卖方案满足:每次买进操作使用完所有的人民币:每次卖出操作卖出所有 ...

随机推荐

  1. spring中bean的作用域属性single与prototype的区别

    https://blog.csdn.net/linwei_1029/article/details/18408363

  2. gitlab多人协同工作

    gitlab多人协同工作 本文为亨利向<Git权威指南>的作者蒋鑫老师的答疑邮件写成. 这里特别感谢蒋鑫老师对我询问gitlab的协同工作流程问题的详细解答. 蒋鑫老师的细致专业的解答让我 ...

  3. linux的MACHINE_START-MACHINE_END(转)

    转自: http://blog.sina.com.cn/s/blog_753fd0b00100t8js.html 在友善mini2440提供的linux2.6.32.2内核中,有如下定义: MACHI ...

  4. idea 的IDE

    idea 是与eclipse齐名的IDE(集成开发工具),以智能闻名,不过对于熟悉eclipse的的用户来说,初次接触idea有些让人搞不清方向,下面介绍一下简单的使用 方式. 1.安装 官网下载ul ...

  5. PageHelper

    https://pagehelper.github.io/ Mybatis分页插件PageHelper简单使用 SpringBoot之分页PageHelper

  6. EasyNVR如何实现跨域鉴权

    EasyNVR提供简单的登录鉴权,客户端通过用户名密码登录成功后,服务端返回认证token的cookie, 后续的接口访问, 服务端从cookie读取token进行校验. 但是, 在与客户系统集成时, ...

  7. Learning an Optimal Policy: Model-free Methods

    http://www.mit.edu/~9.54/fall14/slides/Reinforcement%20Learning%202-Model%20Free.pdf [基于所有.单个样本]

  8. crm高速开发之EntityCollection

    /* 创建者:菜刀居士的博客  * 创建日期:2014年07月07号  */ namespace Net.CRM.OrganizationService {     using System;     ...

  9. B. Two Buttons

    这是Codeforces Round #295 (Div. 2) 的B 题,题意为: 给出n, m, 有两种操作,n 减一 和 n 乘以 2,问最少要多少次操作才能把n 变成 m. Sample te ...

  10. 使用git连接到Github

    直奔主题,使用git连接到Github步骤如下: 1. 安装git yum install git 或者 sudo get-apt install git git-core 2. 全局配置 git c ...