做这道题真的是涨姿势了,一般的CDQ分治都是在序列上进行的,这次是把CDQ分治放树上跑了~

考虑一半的 CDQ 分治怎么进行:

递归处理左区间,处理左区间对右区间的影响,然后再递归处理右区间.

所以,如果是有坐标不递增的斜率优化的话就用 CDQ 分治先处理出左半部分答案,然后将处理好的左区间答案用来更新右区间.

那么,将序列问题拓展到树上后,我们也要选择一个合适的中点来保证分治层数不多,且区间大小均匀.

而树中这个"中点"就是一棵树的重心!!

即当我们处理以 $x$ 为根的子树时(分治区间),先找到重心,然后扣掉重心为根的子树(右区间),然后递归处理 $x$ 为根子树抛去重心为根子树的答案 (递归处理左区间).

递归处理完“左区间”后,计算左对右的影响,那么对重心为根子树的影响就是 $x$ 到重心这条链上所有点.

然后这一部分就不难了,分别按照影响的坐标范围排一下序,然后双指针扫一扫就行了.

处理完对于右区间的贡献后,我们再递归处理右区间:再递归处理重心的每一个儿子即可.

据说这个时间复杂度是 $O(n\log^2n)$ 的

code:

#include <bits/stdc++.h>
#define N 2000006
#define ll long long
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
ll f[N],dep[N],p[N],q[N],l[N];
int edges,root,sn,la,lb,tot,sta[N];
int hd[N],to[N],nex[N],size[N],mx[N],vis[N],A[N],Fa[N],B[N],S[N];
void add(int u,int v)
{
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
bool cmp(int a,int b)
{
return dep[a]-l[a]>dep[b]-l[b];
}
void getroot(int u)
{
size[u]=1,mx[u]=0;
for(int i=hd[u];i;i=nex[i])
{
int v=to[i];
if(vis[v]) continue;
getroot(v);
size[u]+=size[v];
mx[u]=max(mx[u],size[v]);
}
mx[u]=max(mx[u],sn-size[u]);
if(mx[u]<mx[root]) root=u;
}
void dfs(int u)
{
B[++lb]=u;
for(int i=hd[u];i;i=nex[i])
if(!vis[to[i]]) dfs(to[i]);
}
double slope(int a,int b)
{
return (double) (f[a]-f[b])/(dep[a]-dep[b]);
}
void update(int x)
{
if(!tot) return;
int l=1,r=tot,mid,ret=tot;
while(l<=r)
{
mid=(l+r)>>1;
if(slope(sta[mid],sta[mid+1])<p[x]) ret=mid,r=mid-1;
else l=mid+1;
}
f[x]=min(f[x], f[sta[ret]]-dep[sta[ret]]*p[x]+q[x]);
}
void solve(int u)
{
int i,j,rt;
root=0,sn=size[u],getroot(u),vis[rt=root]=1;
if(root!=u) size[u]-=size[rt], solve(u);
la=lb=tot=0;
A[++la]=rt;
for(i=rt;i!=u;i=Fa[i])
{
if(dep[rt]-l[rt]<=dep[Fa[i]]) f[rt]=min(f[rt],f[Fa[i]]-dep[Fa[i]]*p[rt]+q[rt]);
A[++la]=Fa[i];
}
for(int i=hd[rt];i;i=nex[i])
if(!vis[to[i]]) dfs(to[i]);
sort(B+1,B+lb+1,cmp);
for(i=j=1;i<=la;++i)
{
while(j<=lb&&dep[A[i]]<dep[B[j]]-l[B[j]]) update(B[j++]);
while(tot>1&&slope(sta[tot-1],sta[tot])<=slope(sta[tot],A[i])) --tot;
sta[++tot]=A[i];
}
while(j<=lb) update(B[j++]);
for(i=hd[rt];i;i=nex[i])
if(!vis[to[i]])
solve(to[i]);
}
int main()
{
// setIO("input");
int i,j,n,ty;
scanf("%d%d",&n,&ty);
for(i=2;i<=n;++i)
{
scanf("%d%lld%d%lld%lld",&Fa[i],&dep[i],&p[i],&q[i],&l[i]);
add(Fa[i],i);
dep[i]=dep[Fa[i]]+dep[i];
q[i]+=dep[i]*p[i];
}
memset(f,0x3f,sizeof(f)), f[1]=0;
mx[0]=sn=n, size[1]=n, solve(1);
for(i=2;i<=n;++i) printf("%lld\n",f[i]);
return 0;
}

  

BZOJ 3672: [Noi2014]购票 树上CDQ分治的更多相关文章

  1. 【BZOJ 3672】 3672: [Noi2014]购票 (CDQ分治+点分治+斜率优化)**

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

  2. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  3. ●BZOJ 3672 [Noi2014]购票

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3672 题解: 斜率优化DP,点分治(树上CDQ分治...) 这里有一个没有距离限制的简单版: ...

  4. bzoj 3672: [Noi2014]购票 树链剖分+维护凸包

    3672: [Noi2014]购票 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 480  Solved: 212[Submit][Status][D ...

  5. BZOJ 3672: [Noi2014]购票( 树链剖分 + 线段树 + 凸包 )

    s弄成前缀和(到根), dp(i) = min(dp(j) + (s(i)-s(j))*p(i)+q(i)). 链的情况大家都会做...就是用栈维护个下凸包, 插入时暴力弹栈, 查询时就在凸包上二分/ ...

  6. BZOJ 3672 [NOI2014]购票 (凸优化+树剖/树分治)

    题目大意: 略 题面传送门 怎么看也是一道$duliu$题= = 先推式子,设$dp[x]$表示到达$x$点到达1节点的最小花费 设$y$是$x$的一个祖先,则$dp[x]=min(dp[y]+(di ...

  7. BZOJ3672: [Noi2014]购票【CDQ分治】【点分治】【斜率优化DP】

    Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的 ...

  8. bzoj 3672: [Noi2014]购票

    Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. 全国的城市构成了一棵以SZ市为根的有根树,每个城市与它的 ...

  9. BZOJ 3672 [Noi2014]购票 (熟练剖分+凸壳维护)

    题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3672 题意:给出一棵有根树(1为根),边有长度.每个点u有三个属性(len[u], ...

随机推荐

  1. 深度学习-Wasserstein GAN论文理解笔记

    GAN存在问题 训练困难,G和D多次尝试没有稳定性,Loss无法知道能否优化,生成样本单一,改进方案靠暴力尝试 WGAN GAN的Loss函数选择不合适,使模型容易面临梯度消失,梯度不稳定,优化目标不 ...

  2. Go基础编程实践(八)—— 系统编程

    捕捉信号 // 运行此程序,控制台将打印"Waiting for signal" // 按Ctrl + C 发送信号以关闭程序,将发生中断 // 随后控制台依次打印"Si ...

  3. vue报错[Vue warn]: Unknown custom element: <router-Link> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

    vue浏览器报错,如下 vue.runtime.esm.js?2b0e:619 [Vue warn]: Unknown custom element: <router-Link> - di ...

  4. $(...).wordExport is not a function

     参考网址:https://laod.cn/code-audit/jquery-is-not-a-function.html 问题描述: 1.view页面引用的是jquery-1.10.2.min.j ...

  5. Qt Creator 的下载与安装

    一.Qt和Qt Creator的区别 Qt是C++的一个库,或者说是开发框架,里面集成了一些库函数,提高开发效率. Qt Creator是一个IDE,就是一个平台,一个开发环境,类似的比如说VS,也可 ...

  6. 【开发笔记】- yum离线安装

    本方案基本思路是在一个可以联网的系统中下载rpm安装包,然后传到无法联网的目标操作系统,建立安装源,进行安装.为了减少不必要的麻烦,在本地用虚拟机安装一个和目标操作系统一模一样的但是没有安装任何额外软 ...

  7. 使用SAP Cloud Application Programming模型开发OData的一个实际例子

    刚刚过去的SAP TechEd上,SAP CTO Juergen Mueller向外界传递了一个重要的信息:身处云时代大环境下的SAP从业者,在SAP云平台上该如何选择适合自己的开发方式? Juerg ...

  8. Web开发基础知识

    综述 最近开始Java Web方面的工作,千里之行始于足下,我们在开发过程中要善于总结自己遇到的问题.善于管理一些优秀的代码片段.本文的主要内容是Web开发的基础知识,对于大牛来说可以忽略,对于初入W ...

  9. idea2019的安装与激活

    1.安装及相关资料下载 链接:https://pan.baidu.com/s/1njKjorAvaWftuGCvCQzP3A 提取码:r8h8 2.安装步骤 几乎是傻瓜式的安装,点击下一步即可 注意两 ...

  10. 我的oracle 健康检查报告

    最近一直想用sql来生成oracle的健康检查报告,这样看起来一目了然,经过网上搜资料加自己整理终于算是成型了,部分结果如下图所示, 具体参考附件,恳请广大网友看看是否还有需要添加的地方. DB_he ...