题意:给定带点权边权的树,定义路径的花费=路径边权和e+起点点权w[s]*终点点权w[t]。N<2e5,e,w<1e6;

思路:首先,需要树分治。 然后得到方程dp[i]=min{ dis[i]+dis[j]+w[i]*w[j] },很显然需要斜率优化。

注意维护凸包的时候是需要保证w[j]是单调的,这样才能用不等式维护队尾。  由于w[i]不是对应的队尾,所以我们还要二分凸包。

还有个问题,怎么确定我们得到的i和j不是在同一个子树呢? 因为如果在一颗子树的时候dp[i]=dis[i]+dis[j]+w[i]*w[j]-2*dis[LCA]。 其实没必要考虑这个问题,因为当LCA为根的时候会更新答案。(这一点想不到估计要很难去维护了)

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn],To[maxn],Len[maxn],cnt;
int sz[maxn],son[maxn],rt,all,vis[maxn],S[maxn],tot;
ll ans[maxn],a[maxn],dis[maxn],sum; int q[maxn],top;
bool cmp(int x,int y)
{
int xx=x,yy=y;
if(a[xx]==a[yy]) return dis[xx]<dis[yy];
return a[xx]<a[yy];
}
ll getans(int p,int k)
{
return dis[k]+dis[p]+a[p]*a[k];
}
void add(int u,int v,int w)
{
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=w;
}
void dfs1(int u,int f)
{
sz[u]=; son[u]=;
for(int i=Laxt[u];i;i=Next[i]){
if(To[i]!=f&&!vis[To[i]]) {
dfs1(To[i],u);
sz[u]+=sz[To[i]];
son[u]=max(son[u],sz[To[i]]);
}
}
son[u]=max(son[u],all-son[u]);
if(son[u]<son[rt]) rt=u;
}
void cal(int p)
{
if(top==) return ;int L=,R=top-,Mid;
ans[p]=min(ans[p],getans(p,q[top]));
while(L<=R){
Mid=(L+R)>>;
ll tmp1=getans(p,q[Mid]),tmp2=getans(p,q[Mid+]);
if(tmp1<tmp2) R=Mid-,ans[p]=min(ans[p],tmp1);
else L=Mid+,ans[p]=min(ans[p],tmp2);
}
}
void get(int u,int f)
{
cal(u);
for(int i=Laxt[u];i;i=Next[i])
if(To[i]!=f&&!vis[To[i]]) get(To[i],u);
}
bool check(int p){
return (dis[p]-dis[q[top]])*(a[p]-a[q[top-]])<=
(dis[p]-dis[q[top-]])*(a[p]-a[q[top]]);
}
void ADD(int p)
{
if(top&&a[p]==a[q[top]]&&dis[p]<dis[q[top]]) top--;
while(top>&&check(p)) top--;
q[++top]=p;
}
void get(int u,int f,ll D)
{
dis[u]=D; sz[u]=; S[++tot]=u;
for(int i=Laxt[u];i;i=Next[i])
if(To[i]!=f&&!vis[To[i]]){
get(To[i],u,D+Len[i]);
sz[u]+=sz[To[i]];
}
}
void solve(int u,int f)
{
vis[u]=; dis[u]=;
top=; tot=; S[++tot]=u;
for(int i=Laxt[u];i;i=Next[i]){
if(!vis[To[i]]&&To[i]!=f)
get(To[i],u,Len[i]);
}
sort(S+,S+tot+,cmp);
rep(i,,tot) ADD(S[i]);
rep(i,,tot) cal(S[i]);
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i];
if(!vis[v]&&v!=f) {
all=sz[v]; rt=;
dfs1(v,); solve(rt,);
}
}
}
int main()
{
int N,u,v,w;
scanf("%d",&N); son[]=N+;
rep(i,,N) scanf("%lld",&a[i]);
rep(i,,N) ans[i]=a[i]*a[i];
rep(i,,N-){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w); add(v,u,w);
}
all=N; rt=;
dfs1(,); solve(rt,);
rep(i,,N) sum+=ans[i];
printf("%lld\n",sum);
return ;
}

Gym - 101002K:YATP (树分治+二分+斜率优化)的更多相关文章

  1. 【BZOJ4311】向量(线段树分治,斜率优化)

    [BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...

  2. Codeforces Gym 101175F - Machine Works(CDQ 分治维护斜率优化)

    题面传送门 首先很明显我们会按照 \(d_i\) 的顺序从小到大买这些机器,故不管三七二十一先将所有机器按 \(d_i\) 从小到大排序. 考虑 \(dp\),\(dp_i\) 表示在时刻 \(d_i ...

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

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

  4. 【洛谷p3994】Highway 二分+斜率优化DP

    题目大意:给你一颗$n$个点的有根树,相邻两个点之间有距离,我们可以从$x$乘车到$x$的祖先,费用为$dis\times P[x]+Q[x]$,问你除根以外每个点到根的最小花费. 数据范围:$n≤1 ...

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

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

  6. LOJ 2353 & 洛谷 P4027 [NOI2007]货币兑换(CDQ 分治维护斜率优化)

    题目传送门 纪念一下第一道(?)自己 yy 出来的 NOI 题. 考虑 dp,\(dp[i]\) 表示到第 \(i\) 天最多有多少钱. 那么有 \(dp[i]=\max\{\max\limits_{ ...

  7. LOJ 2585 「APIO2018」新家 ——线段树分治+二分答案

    题目:https://loj.ac/problem/2585 算答案的时候要二分! 这样的话,就是对于询问位置 x ,二分出一个最小的 mid 使得 [ x-mid , x+mid ] 里包含所有种类 ...

  8. [NOI2007]货币兑换 cdq分治,斜率优化

    [NOI2007]货币兑换 LG传送门 妥妥的\(n \log n\)cdq做法. 这题用cdq分治也可以\(n \log n\)但是在洛谷上竟然比一些优秀的splay跑得慢真是见了鬼了看来还是人丑常 ...

  9. [NOI2007]货币兑换 「CDQ分治实现斜率优化」

    首先每次买卖一定是在某天 $k$ 以当时的最大收入买入,再到第 $i$ 天卖出,那么易得方程: $$f_i = \max \{\frac{A_iRate_kf_k}{A_kRate_k + B_k} ...

随机推荐

  1. kali-rolling安装nessus 7并创建扫描任务教程

    一.下载 下载页面:https://www.tenable.com/downloads/nessus 如果自己安装的kali是32位的则选择上边的32位版本下载 二.安装 直接用dpkg安装即可: d ...

  2. listener.ora和tnsnames.ora格式解析

    listener.ora是oracle数据库服务端的监听配置文件,包括协议.IP地址和端口等内容:tnsnames.ora是oracle数据库客户端的连接配置文件,也是对应的协议.IP地址和端口等内容 ...

  3. Vscode extensions开发

    Vscode extensions开发   1◆ generatorcode install npm install -g yo generator-code     2◆ 步骤 yo code   ...

  4. matlab plot line settings

  5. 如何快速成为一名Linux运维工程师

    如今的互联网,绝大多数的网站.服务.游戏均是跑在Linux上面的,虽说Linux发行版众多,只要玩熟了一种发行版,了解了Linux精髓.基本架构.设计原理,其他都是触类旁通的,千万不要在选择哪一发行版 ...

  6. day7-python打开文件方式

    文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 基本操作 import codecs #主要用来解决乱码问题 f = codecs.open('1. ...

  7. X86汇编语言实现的贪吃蛇游戏

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  8. Excel 数据读入到DataSet

    using System; using System.Collections.Generic; using System.Linq; using System.Data; using System.I ...

  9. DataTable数据统计方法

    调用方法: public object Compute(string strExpression,string strFilter) 参数说明: strExpression:要计算的表达式字符串,基本 ...

  10. JavaWeb:动作标识

    动作标识 一.包含文件标识<jsp:include> 1.介绍 用于向当前页面中包含其他文件.被包含的文件可以是动态文件,也可以是静态文件 2.语法格式 <jsp:include p ...