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

解析

第一道完全自己做出来的黑题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=disvlv<=disu,uancvmin(dpu+pv×(disvdisu)+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;
}
/**/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/317402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDU1394(权值线段树)

HDU1394(权值线段树) 题意&#xff1a; 给定一个0到n-1的数字组成的序列&#xff0c;可以将序列进行左移任意次&#xff0c;求所能组成序列的逆序对的最小值 题解&#xff1a; 利用权值线段树&#xff0c;我们先求出当前序列所能组成的逆序对&#xff0c; 然后依次左移动 当…

P8339-[AHOI2022]钥匙【虚树,扫描线】

正题 题目连接:https://www.luogu.com.cn/problem/P8339 题目大意 给出nnn个点的一棵树&#xff0c;每个点有钥匙或者宝箱&#xff0c;有不同的颜色。 mmm次询问&#xff0c;从xxx走到yyy&#xff0c;走到钥匙时会拾取钥匙&#xff0c;走到宝箱时如果有同色的钥匙那么就会消耗…

[HDU 6157]The Karting(DP)

[HDU 6157]The Karting description solution 先用前缀和求出di:1→id_i:1\rightarrow idi​:1→i 的距离 前缀和满足&#xff1a;若在iii点进行方向改变&#xff0c;则iii产生的贡献是一定的&#xff0c;可以先累计贡献 也就是说真正的路径怎么走&#xff0c;我们是不关心…

.NET 开源简史

现在在微软开发开源软件是很一件正常的事情——但在 2007 年&#xff0c;当时我刚加入微软&#xff0c;那时候可不是这么一回事。微软花了好几年时间才找到正确的方向&#xff0c;让微软这艘大船顺着开源之风向前航行。现在回头远望过去那些曾经面临的挑战&#xff0c;我们一笑…

P2617 Dynamic Rankings(整体二分)

P2617 Dynamic Rankings 题意: 待修改的区间最值问题 题解&#xff1a; 整体二分天然带有修改性 整体二分做不带修改的区间最值—>看这里 现在待修改&#xff0c;我们可以将第l位修改为x&#xff0c;因为我们是用树状数组来维护的&#xff0c;所以把这个过程拆分成将第l个…

模板:虚树

所谓虚树&#xff0c;就是虚了的树 &#xff08;逃&#xff09; 前言 在有些时候&#xff0c;我们只关心树上的某些特殊点&#xff0c;问题中的整体规模较大&#xff0c;但是这些特殊点往往比较稀疏&#xff0c;这个时候就可以使用虚树&#xff0c;只保留树上的关键点&#x…

P8340-[AHOI2022]山河重整【dp,倍增】

正题 题目链接:https://www.luogu.com.cn/problem/P8340 题目大意 给出一个nnn和模数PPP。求有多少个在1∼n1\sim n1∼n中选择若干个数的集合SSS&#xff0c;满足1∼n1\sim n1∼n中的每个数都可以表示成SSS的某个子集的和。 1≤n≤5105,2≤P≤1.11091\leq n\leq 5\times 10^5…

[LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心+贪心)

[LOJ 6042]「雅礼集训 2017 Day7」跳蚤王国的宰相 description solution 一个到所有节点距离和最小的节点 ⇔\Leftrightarrow⇔ 树的重心&#xff08;满足最重的儿子最轻&#xff0c;每个儿子siz≤n2\le\frac{n}{2}≤2n​&#xff09; 显然原树的重心答案为0 对于点iii&am…

由优劣语言之争引起的思考

由优劣语言之争引起的思考#欲使其灭亡&#xff0c;必使其疯狂昨天上午由阿里云中间件公众号和架构师小秘圈公众号发布的一篇文章《天天敲代码会使人变聪明么》在.net开发者中掀起了一阵巨浪&#xff0c;文章中提到的语言的先进与落后之争让基于.net开发者们义愤填膺&#xff0c…

P1527 [国家集训队]矩阵乘法

P1527 [国家集训队]矩阵乘法 题意&#xff1a; 给你一个 nn 的矩阵&#xff0c;每次询问一个子矩形的第 k 小数。 题解&#xff1a; 整体二分稍微加强化 模板题是一个序列&#xff0c;现在升级成一个矩阵求&#xff0c;做法和原理都是一样的 使用整体二分解决的题目&#x…

[LOJ #521]「LibreOJ β Round #3」绯色 IOI(抵达)(结论)

#521. 「LibreOJ β Round #3」绯色 IOI&#xff08;抵达&#xff09; description solution 因为点的庇护所不能为自身&#xff0c;题目背景在树上&#xff0c;有结论一定是两个相邻点互为庇护所 所以树一定要能两两完美匹配才有解 判断完有解后就是构造解了&#xff0c;…

UOJ#310-[UNR #2]黎明前的巧克力【FWT】

1# 正题 题目链接:https://uoj.ac/problem/310 题目大意 给出一个长度为nnn的序列&#xff0c;求有多少种方案找出两个集合S,TS,TS,T使得这两个集合的异或和相等。 1≤n≤1061\leq n\leq 10^61≤n≤106 解题思路 可以转换为找到一个异或和为000的集合SSS&#xff0c;产生2∣S…

ybtoj洛谷P4426:毒瘤(虚树,环套树,暴力)

传送门 解析 顾名思义&#xff0c;十分毒瘤 但有一说一&#xff0c;相对来说这题没有之前做的那两个黑题那么&#xff08;重读&#xff09;恶心 而且本题如果放在考场上&#xff0c;暴力枚举非树边的状态dp就可以拿到70分的好成绩&#xff08;改一改能改到75&#xff09; 现…

微软是如何使用 C# 重写 C# 编译器并将其开源的

Roslyn 是 C# 和 Visual Basic.NET 开源编译器的代号。这篇文章将介绍它是如何从微软过去的十年至暗时刻走出来&#xff0c;成为开源跨平台的 C# 和 VB 公共语言引擎。我于 2005 年加入微软&#xff0c;也就是在.NET 2.0 发布之前&#xff0c;当时微软内部已经开始在讨论 Rosly…

P3332 [ZJOI2013]K大数查询(整体二分做法)

P3332 [ZJOI2013]K大数查询 题意: 题解&#xff1a; 利用整体二分来做&#xff0c;这个题和P3834 【模板】可持久化线段树 2的区别在于本题的修改是区间修改&#xff0c;所以将里面的树状数组改成线段树就行&#xff0c;区间修改区间查询 但是不知道为什么我调了一阵子也不对…

[APIO2020]交换城市(交互+kruskal重构树)

[APIO2020]交换城市 description solution 如果u,vu,vu,v存在于一条链上&#xff08;只有两个点度数为111其余点度数为222&#xff09;则无解&#xff0c;否则必有解 如图&#xff0c;不管是哪个点度数>2>2>2&#xff0c;都可以有解 以蓝色为例&#xff0c;第二个…

P3320:寻宝游戏(生成树)

解析 大结论题… 实在是不知道这题和虚树有半毛钱关系吗… 引理 给出一个按照dfs排列的点集S{a1,a2…ak} 它们的极小联通子树的边权和的二倍等于∑dis(a1,a2)dis(a2,a3)...dis(ak−1,ak)dis(ak,a1)\sum dis(a_1,a_2)dis(a_2,a_3)...dis(a_k-1,a_k)dis(a_k,a_1)∑dis(a1​,a2​…

P5333-[JSOI2019]神经网络【dp,容斥】

正题 题目链接:https://www.luogu.com.cn/problem/P5333 题目大意 给出nnn棵树&#xff0c;第iii棵树有kik_iki​个点&#xff0c;每棵树上的每个点和其它树上的所有点都有连边。 求这棵树有多少条哈密顿回路。 答案对998244353998244353998244353取模。 ∑i1nki≤5000\sum…

如何在ASP.NET Core程序启动时运行异步任务(1)

原文&#xff1a;Running async tasks on app startup in ASP.NET Core (Part 1)作者&#xff1a;Andrew Lock译者&#xff1a;Lamond Lu背景当我们做项目的时候&#xff0c;有时候希望自己的ASP.NET Core应用在启动前执行一些初始化逻辑。例如&#xff0c;你希望验证配置是否合…

扫描线讲解

参考文章&#xff1a; 线段树扫描线&#xff08;有关扫描线的理解&#xff09; 线段树扫描线&#xff08;基本原理&#xff09; 扫描线 第二个文章里面的图很生动&#xff1a; 我总结一下就是&#xff1a;将所给图形的横坐标全部记录&#xff0c;纵坐标记录为扫描线 然后对与…