解析

第一道完全自己做出来的黑题awa
(如果不算那道感觉完全是恶评的石油的话)
然而连写带调整了3.5h…

容易想到链的做法
设ancxanc_xancx​表示x的祖先,disxdis_xdisx​表示x到1的距离
则有:
dpv=min⁡disv−lv<=disu,u∈ancv(dpu+pv×(disv−disu)+qvdp_v=\min_{dis_v-l_v<=dis_u,u\in anc_v}(dp_u+p_v\times (dis_v-dis_u)+q_vdpv​=disv​−lv​<=disu​,u∈ancv​min​(dpu​+pv​×(disv​−disu​)+qv​
这个就可以斜优了

然后考虑如何上树
树比较恶心的地方就是我们的队列会随着dfs分支的改变而变化
难以解决

换个思路
考虑点分治
对与当前的重心 rt,
先把rt到1的那个联通块递归solve掉
然后再把联通块内rt的返祖链取下来
再dfs找到所有联通块内的其他点
按照能到达的最大高度sort一下
然后做个指针动态维护这个凸包,二分更新就行了

代码

#include<bits/stdc++.h>
using namespace std;
#define ll __int128
#define inf (n+1)
//#define debug(...) fprintf(stderr,__VA_ARGS__)
const int N=2e5+100;
const int M=2e5+10500;
const double eps=1e-5;
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x<0){putchar('-');x=-x;}if(x>9) write(x/10);putchar('0'+x%10);return;
}int n,m;
int debug(0);struct node{int to,nxt;ll w;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y,ll w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;return;
}ll dp[N],P[N],Q[N],dis[N],l[N];
int fa[N],siz[N],mx[N],S,rt;
int que[N],num1;
int v[N],num2;
bool vis[N];void find(int x,int f){siz[x]=1;mx[x]=0;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f||vis[to]) continue;find(to,x);siz[x]+=siz[to];mx[x]=max(mx[x],siz[to]);}   mx[x]=max(mx[x],S-siz[x]);if(!rt||mx[rt]>mx[x]) rt=x;return;
}void dfs(int x,int top){que[++num1]=x;//if(debug) printf("dfs:x=%d f=%d tot=%d\n",x,f,tot);if(x==top) return;dfs(fa[x],top);return;
}#define X(o) dis[o]
#define Y(o) dp[o]
int q[N],le,ri;inline void upd(int x){int st=le,ed=ri;while(st<ed){int mid=(st+ed)>>1,o=q[mid];if(dis[x]-dis[o]>l[x]||(mid<ri&&P[x]*(X(q[mid+1])-X(q[mid]))>=(Y(q[mid+1])-Y(q[mid])))) st=mid+1;else ed=mid;//if(debug) printf("    mid=%d o=%d d=%lld %d||(%d&&%d) (%d %d)\n",mid,o,(long long)(dis[x]-dis[o]),dis[x]-dis[o]>l[x],mid<tot,P[x]*(X(q[num+1])-X(q[num]))>=(Y(q[num+1])-Y(q[num])),st,ed);}if(st==ed&&dis[x]-dis[q[st]]<=l[x]){int u=q[st];dp[x]=min(dp[x],P[x]*(dis[x]-dis[u])+dp[u]+Q[x]);if(debug) printf("  update: x=%d u=%d dp=%lld\n",x,u,(long long)dp[x]);}return;
}inline void add(int x){if(debug) printf("  add:x=%d (%lld %lld)\n",x,(long long)X(x),(long long)Y(x));while(le<ri&&(Y(q[le])-Y(x))*(X(q[le+1])-X(q[le]))>=(Y(q[le+1])-Y(q[le]))*(X(q[le])-X(x))) ++le;q[--le]=x;if(debug) for(int i=le;i<=ri;i++) printf("[%d]:(%lld %lld) ",q[i],(long long)X(q[i]),(long long)Y(q[i]));if(debug) putchar('\n');return;
}void get(int x,int f){v[++num2]=x;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f||vis[to]) continue;get(to,x);}return;
}
int findtop(int x){return fa[x]&&!vis[fa[x]]?findtop(fa[x]):x;
}
int calc(int x,int f){int res(1);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f||vis[to]) continue;res+=calc(to,x);}return res;
}
bool cmp(int x,int y){return dis[x]-l[x]>dis[y]-l[y];
}
void solve(int x){S=calc(x,0);rt=0;find(x,0);x=rt;vis[x]=1;int top=findtop(x);if(debug) printf("\nsolve: %d (S=%d top=%d)\n",x,S,top);if(fa[x]&&!vis[fa[x]]){solve(fa[x]);}if(debug) printf("\nbeginwork:%d\n",x);num1=0;num2=0;dfs(x,top);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(vis[to]||to==fa[x]) continue;get(to,x);}sort(v+1,v+1+num2,cmp);if(debug){printf("que:");for(int i=1;i<=num1;i++) printf("%d ",que[i]);putchar('\n');printf("v:");for(int i=1;i<=num2;i++) printf("%d ",v[i]);putchar('\n');}for(int i=1;i<=num1;i++){int u=que[i];if(dis[x]-dis[u]>l[x]) break;dp[x]=min(dp[x],dp[u]+P[x]*(dis[x]-dis[u])+Q[x]);}int pl=1;ri=n;le=n+1;for(int i=1;i<=num2;i++){while(pl<=num1&&dis[v[i]]-l[v[i]]<=dis[que[pl]]){add(que[pl]);++pl;}upd(v[i]);}for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(vis[to]) continue;solve(to);}return;
}void init(int x,int f){for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dis[to]=dis[x]+p[i].w;init(to,x);}return;
}
int main(){#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);
#endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();int zhennanrencongbuxiebufenfen=read();//assert(zhennanrencongbuxiebufenfen<=3);for(int i=2;i<=n;i++) dp[i]=2e18;dp[1]=0;for(int i=2;i<=n;i++){fa[i]=read();ll w=read();P[i]=read();Q[i]=read();l[i]=read();addline(fa[i],i,w);addline(i,fa[i],w);}init(1,0);siz[1]=n;solve(1);for(int i=2;i<=n;i++) write(dp[i]),putchar('\n');return 0;
}
/**/

P2305 [NOI2014] 购票(点分治、斜率优化)相关推荐

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

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

  2. P2305 [NOI2014]购票

    P2305 [NOI2014]购票 题目描述 详见:P2305 [NOI2014]购票 Solution 写出一个朴素的DP可以看出显然是一个斜率优化,且是在树上求解答案. 因此用点分治维护树上斜率优 ...

  3. 【BZOJ3963】[WF2011]MachineWorks cdq分治+斜率优化

    [BZOJ3963][WF2011]MachineWorks Description 你是任意性复杂机器公司(Arbitrarily Complex Machines, ACM)的经理,公司使用更加先 ...

  4. BZOJ 1492: [NOI2007]货币兑换Cash [CDQ分治 斜率优化DP]

    传送门 题意:不想写... 扔链接就跑 好吧我回来了 首先发现每次兑换一定是全部兑换,因为你兑换说明有利可图,是为了后面的某一天两种卷的汇率差别明显而兑换 那么一定拿全利啊,一定比多天的组合好 $f[ ...

  5. NOI2007 货币兑换 - CDQ分治斜率优化dp

    斜率优化dp维护一个凸壳.如果\(x, y\)坐标都递增,可以用单调队列,如果只有\(x\)递增,可以在凸壳上二分斜率,如果\(x, y\)都不递增,则需要在凸包中插入,可以用平衡树或cdq分治维护. ...

  6. CF932F-Escape Through Leaf【树上启发式合并,CDQ分治,斜率优化dp】

    正题 题面链接:https://www.luogu.com.cn/problem/CF932F 题目大意 nnn个点的一棵树,从xxx跳到yyy(要求yyy在xxx的子树中)会产生Ax∗ByA_x*B ...

  7. 【BZOJ2149】拆迁队,分治+斜率优化DP

    传送门 思路还不错的一道题目,难度不大,但是我在写的时候出了一些细节上的错误 显然题目中的两问都可以通过DP来解决 f[i]f[i]表示保留旧房子ii时,1-i1-i最多能保留多少个旧房子 g[i]g ...

  8. 时空旅行(dfs序+线段树分治+斜率优化)

    时空旅行 题意: 给定一棵以000为根的树,每个节点上有信息(一种是增加某个带权三维点,一种是删除某个带权三维点):询问要求从根节点到某个节点的信息总和中找到一个最优带权三维点. 思路: 首先,每个星 ...

  9. 【分治+斜率优化】BZOJ2149拆迁队 CF660F Bear and Bowling 4

    BZOJ2149拆迁队 [题目] 原题地址 题目大意不想写. [题目分析] 斜率优化的dp是显然的,然后就是怎么维护的问题了. [解题思路] 这题显然就是一个斜率优化的dp,然后分治的时候维护一下凸壳 ...

最新文章

  1. SDN第4次上机作业
  2. Google研究员Ilya Sutskever:成功训练LDNN的13点建议
  3. Java集合细节(三):subList的缺陷
  4. 循环——批量处理数据
  5. 参数化的RBAC模型
  6. Linux Arch目录下处理器体系架构介绍
  7. tsql是mysql中的吗_Mysql中的sql是如何执行的
  8. 数据的属性及“数据的特征”
  9. 图片维度不匹配_内容审核基础:审核方式、流程与审核维度
  10. 并发-2-Thread和Runnable的API
  11. linux系统开机启动流程
  12. cdr怎么做文字路径_CorelDRAW如何制作环绕圆形的路径文字
  13. 超融合服务器系统,超融合服务器|超融合架构|超融合一体机|业务系统一体机
  14. php 时分秒选择联动,jquery.datepair日期时分秒选择器
  15. 使用RecyclerView自定义实现二级联动列表
  16. 苹果手机2019年什么时候出新款_[创立24周年]焕新,不换我初心 因强大而简单.智者,驭时而进 - 手机数码电玩维修...
  17. 【阿里巴巴】学习Java在面试过程中跳槽成功的心得总结
  18. DXO 评测华为p20pro说的halo effect是什么
  19. android调用系统发送短信
  20. excel中怎么显示数字/英文时间

热门文章

  1. php写带分页的留言板,php中分页程序之基于留言板详解_PHP教程
  2. typora插入代码设置_Typora基本功能介绍
  3. 学计算机要买什么样的电脑,大学开学要买电脑吗?又要买什么样的电脑?看准这些再买也不迟!...
  4. linux新建文件夹明率,linux新建文件和文件夹命令
  5. java压缩成.tar_java压缩tar.gz | 学步园
  6. .gpg 进程 linux,小知识之Linux系统中的最大进程数,最大文件描述,最大线程数...
  7. 读数据库遇到空就进行不下去_如何保证缓存与数据库的双写一致性?
  8. msdn画圆弧函数_画直线不简单!python-matplotlib告诉你为什么
  9. xcode 修改 infodictionary_安卓系统修改复位键生效时间
  10. leetcode19. 删除链表的倒数第 N 个结点