我们都做过一道题(?)货币兑换,是用cdq分治来解决不单调的斜率优化

现在它放到了树上..

总之先写下来dp方程,$f[i]=min\{f[j]+(dis[i]-dis[j])*p[i]+q[i]\} ,j是i的祖先,dis[i]-dis[j]<=l[i]$ ,其中dis[i]表示1号点到i号点的距离

可以很明显的看出斜率优化,但我们要放到树上做

于是就运用点分治的思想来找重心(正如普通的cdq是找中点一样)

步骤是这样的:

1.对于根为x的一个子树,我们先找到它的重心rt

2.把rt的子树刨掉,但留下rt,然后递归地再做x,目的是先算出祖先们的答案,为更新孩子们做准备

3.把rt在子树x中的祖先按深度排序,把rt的子树(不包括rt)按照它们最远能到的祖先的深度排序,然后一边插祖先维护一个凸包,一边给孩子统计答案

4.递归地做rt的子节点

斜率优化的细节就不写了(因为全是蒙出来的)

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define ll long long
using namespace std;
const int maxn=2e5+,inf=0x3f3f3f3f; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Edge{
int b,ne;ll l;
}eg[maxn*];
int fa[maxn][],egh[maxn],ect;
int N,NN,dep[maxn],ldep[maxn];
int siz[maxn],root;
int cnt[maxn],tmpl[maxn],tmpr[maxn],pct;
int stk[maxn];
ll dp[maxn],dis[maxn],p[maxn],q[maxn],l[maxn];
bool vis[maxn]; void dfs1(int x){
int i;
for(i=;fa[x][i-]&&fa[fa[x][i-]][i-];i++) fa[x][i]=fa[fa[x][i-]][i-];
int y=x;for(ll j=l[x];i>=;i--){
if(fa[y][i]&&dis[y]-dis[fa[y][i]]<=j)
j-=dis[y]-dis[fa[y][i]],y=fa[y][i];
}
if(y!=x) ldep[x]=dep[y];
else ldep[x]=-; for(i=egh[x];i;i=eg[i].ne){
int b=eg[i].b;
dis[b]=dis[x]+eg[i].l;
dep[b]=dep[x]+;
dfs1(b);
}
} void getroot(int x,int smsiz,int &ms,int &root){
siz[x]=;int mm=;
for(int i=egh[x];i;i=eg[i].ne){
int b=eg[i].b;if(vis[b]) continue;
getroot(b,smsiz,ms,root);siz[x]+=siz[b];
mm=max(mm,siz[b]);
}mm=max(mm,smsiz-siz[x]);
if(mm<=ms) ms=mm,root=x;
}
void getson(int x){
tmpr[++pct]=x;
for(int i=egh[x];i;i=eg[i].ne){
int b=eg[i].b;if(vis[b]) continue;
getson(b);
}
} inline bool cmp(int a,int b){
return ldep[a]>ldep[b];
} inline double getk(int a,int b){
return (double)(dp[a]-dp[b])/(dis[a]-dis[b]);
} void cdq(int x,int s){
if(s<=) return;
int rt,ms=inf;
getroot(x,s,ms,rt);
if(x!=rt){
int sms=s,mmm=inf;
for(int i=egh[rt];i;i=eg[i].ne) vis[eg[i].b]=,sms-=siz[eg[i].b];
cdq(x,sms);
}int l=;
for(int i=rt;i!=fa[x][];i=fa[i][]) tmpl[++l]=i;
pct=;
for(int i=egh[rt];i;i=eg[i].ne) getson(eg[i].b);
sort(tmpr+,tmpr+pct+,cmp); int sh=;
for(int i=,j=;i<=pct&&ldep[tmpr[i]]!=-;i++){
for(;j<=l&&dep[tmpl[j]]>=ldep[tmpr[i]];j++){
while(sh>&&getk(stk[sh],stk[sh-])<=getk(stk[sh],tmpl[j])) --sh;
stk[++sh]=tmpl[j];
}
if(sh){
int k=stk[];
if(sh!=){
int a=,b=sh-;
while(a<=b){
int m=(a+b)>>;
if(getk(stk[m],stk[m+])<=p[tmpr[i]]) k=stk[m],b=m-;
else k=stk[m+],a=m+;
}
}
dp[tmpr[i]]=min(dp[tmpr[i]],dp[k]+(dis[tmpr[i]]-dis[k])*p[tmpr[i]]+q[tmpr[i]]);
}
}
for(int i=egh[rt];i;i=eg[i].ne){
cdq(eg[i].b,siz[eg[i].b]);
}
} inline void adeg(int a,int b,int l){
eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
} int main(){
int i,j,k;
N=rd();rd();
for(i=;i<=N;i++){
int a=rd(),b=rd();p[i]=rd(),q[i]=rd(),l[i]=rd();
adeg(a,i,b);fa[i][]=a;
}ldep[]=-;dep[]=;dfs1();
memset(dp,,sizeof(dp));dp[]=;
cdq(,N);
for(i=;i<=N;i++) printf("%lld\n",dp[i]);
return ;
}

bzoj3672/luogu2305 购票 (运用点分治思想的树上cdq分治+斜率优化dp)的更多相关文章

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

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

  2. 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治

    题目描述  给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...

  3. [Noi2014]购票 斜率优化DP+可持久化凸包

    貌似网上大部分题解都是CDQ分治+点分治然后再斜率优化DP,我貌似并没有用这个方法. 这一题跟这题有点像,只不过多了一个l的限制 如果说直接跑斜率优化DP,存储整个序列的话,显然是不行的,如图所示(图 ...

  4. 【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 ...

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

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

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

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

  7. UOJ#7 NOI2014 购票 点分治+凸包二分 斜率优化DP

    [NOI2014]购票 链接:http://uoj.ac/problem/7 因为太麻烦了,而且暴露了我很多学习不扎实的问题,所以记录一下具体做法. 主要算法:点分治+凸包优化斜率DP. 因为$q_i ...

  8. BZOJ 3672: [Noi2014]购票 树上CDQ分治

    做这道题真的是涨姿势了,一般的CDQ分治都是在序列上进行的,这次是把CDQ分治放树上跑了~ 考虑一半的 CDQ 分治怎么进行: 递归处理左区间,处理左区间对右区间的影响,然后再递归处理右区间. 所以, ...

  9. BZOJ 3963: [WF2011]MachineWorks [CDQ分治 斜率优化DP]

    传送门 当然了WF的题uva hdu上也有 你的公司获得了一个厂房N天的使用权和一笔启动资金,你打算在这N天里租借机器进行生产来获得收益.可以租借的机器有M台.每台机器有四个参数D,P,R,G.你可以 ...

随机推荐

  1. docker for windows 10 添加阿里云镜像仓库无效问题

    原来一直是用cmd来执行docker 命令的,结果今天发现不行了,改了镜像仓库也pull不下来. 后来换用powerShell执行docker pull 才成功.大家可以试试 win+R  运行 po ...

  2. [Oracle]如何取Control File 的Dump

    ]如何取Control File 的Dump: SQL> alter session set events 'immediate trace name controlf level 3';SQL ...

  3. C#实现.Net对邮件进行DKIM签名和验证,支持附件,发送邮件签名后直接投递到对方服务器(无需己方邮件服务器)

    项目地址 https://github.com/xiangyuecn/DKIM-Smtp-csharp 主要支持 对邮件进行DKIM签名,支持带附件 对整个邮件内容(.eml文件)的DKIM签名进行验 ...

  4. “论 ofo 是如何影响今日头条发展的”

    近段时间, ofo 小黄车押金难退的消息频频曝出.尽管 OFO 已经宣布押金只能在线上退还,但是线上退押金也难,因此很多的用户还是选择到 ofo 北京总部“要个说法”.记者昨天在现场发现,位于北京中关 ...

  5. 12.18 Daily Scrum

    最近大家确实都很忙,所以所有功能的实现要等到下周.   Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表.             ...

  6. T-shirt 0 0....

    老师给我这件T-shirt的目的是为了让我减肥吗...... 听说了pbb的事迹好感动 //偷偷吐槽一句,那个全套吉米多维奇可以报销吗...我就看了2行........ 吓得我赶紧看了一下浴盆的气球

  7. app推广及主要代码

    app推广:      一.基本情况       我们把推广和调研都放在了一起,主要是调研,主要通过调查问卷和直接访问的方式,让调查的人能够看到我们app的主要功能, 然后做出评价和对此改善的意见.调 ...

  8. Alpha冲刺之事后诸葛亮

    组长博客 作业博客 项目Postmortem 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件针对的是福大学子来到食堂会犹豫不决无法决定吃什么 ...

  9. 20172319 《Java程序设计教程》第8周学习总结

    20172319 2018.04.24-05.03 <Java程序设计教程>第8周学习总结 目录 教材学习内容总结 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考 ...

  10. 【软件工程Ⅱ】作业二 |分布式版本控制系统Git的安装与使用

    本次作业的要去来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 远程库地址:https://github.com/Mol ...