首页 > 其他分享 >Building Bridges 题解

Building Bridges 题解

时间:2023-07-18 13:11:57浏览次数:43  
标签:Building Bridges int 题解 include 2h id

Building Bridges

题目大意

连接两根柱子 \(i,j\) 的代价是 \((h_i-h_j)^2+\sum\limits_{k=j+1}^{i-1}w_k\),连接具有传递性,求将 \(1,n\) 连接的最小代价。

思路分析

斜率优化 DP 板题。

设 \(f_i\) 表示考虑到前 \(i\) 根柱子并强制选择第 \(i\) 根柱子的最小代价,所求即 \(f_n\)。则容易列出状态转移方程:

\[f_i=\min_{j<i}(f_j+(h_i-h_j)^2+\sum_{k=j+1}^{i-1}w_k) \]

设 \(s\) 为 \(w\) 的前缀和,即 \(s_i=\sum\limits_{j=1}^iw_j\),则方程可化为:

\[f_i=\min_{j<i}(f_j+h_i^2-2h_ih_j+h_j^2+s_{i-1}-s_{j}) \]

然后是斜率优化经典操作:

\[\begin{aligned}f_i&=f_j+h_i^2-2h_ih_j+h_j^2+s_{i-1}-s_{j}\\f_i-h_i^2-s_{i-1}&=f_j+h_j^2-s_j-2h_ih_j\\(f_i-h_i^2-s_{i-1})&=(-2h_j)(h_i)+(f_j+h_j^2-s_j)\end{aligned} \]

设:

\[\begin{cases}y=f_i-h_i^2-s_{i-1}\\k=-2h_j\\x=h_i\\b=f_j+h_j^2-s_j\end{cases} \]

问题转化为每次插入一条 \(k_i=-2h_i,b_i=f_i+h_i^2-s_i\) 的直线,查询 \(x_i=h_i\) 的最值,用李超线段树优化即可。

代码

自我感觉马蜂可看。

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N=100100,V=1001000;
#define int long long
#define mid ((l+r)>>1)
#define inf 0x3f3f3f3f3f3f3f3f

int n;
int h[N],s[N],f[N];

struct Line{
	int k,b;
}line[N];

int calc(int id,int x){
	return line[id].k*x+line[id].b;
}

bool Less(int id1,int id2,int x){//比较优劣
	return calc(id1,x)<calc(id2,x);
}

struct ST{//简洁的李超线段树
	int a[V<<2];
	void add(int p,int l,int r,int id){
		if(l==r){if(Less(id,a[p],l)) a[p]=id;return ;}
		if(Less(id,a[p],mid)) swap(a[p],id);
		if(Less(id,a[p],l)) add(p<<1,l,mid,id);
		if(Less(id,a[p],r)) add(p<<1|1,mid+1,r,id);
	}
	int query(int p,int l,int r,int x){
		int res=calc(a[p],x);
		if(l==r) return res;
		if(x<=mid) res=min(res,query(p<<1,l,mid,x));
		else res=min(res,query(p<<1|1,mid+1,r,x));
		return res;
	}
}tree;

signed main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
	for(int i=1;i<=n;i++){
		scanf("%lld",&s[i]);
		s[i]+=s[i-1];
	}
	line[0]={0,inf};//初始化第 0 条直线,保证空转移转移不到第 0 条上
	line[1]=Line{-2*h[1],h[1]*h[1]-s[1]};//初始化第一条直线
	tree.add(1,0,V,1);//加入第一条直线
	for(int i=2;i<=n;i++){
		f[i]=tree.query(1,0,V,h[i])+h[i]*h[i]+s[i-1];//查询,移项过去得 f[i]
		line[i]=Line{-2*h[i],f[i]+h[i]*h[i]-s[i]};//新建直线
		tree.add(1,0,V,i);//插入直线
	}
	cout<<f[n]<<'\n';
	return 0;
}

标签:Building,Bridges,int,题解,include,2h,id
From: https://www.cnblogs.com/TKXZ133/p/17562632.html

相关文章

  • [ABC310D] Peaceful Teams 题解
    PeacefulTeams题目大意将\(n\)个人分成\(T\)组,要求每组不能包含敌对的人,问有多少种分法。思路分析注意到\(n,T\)均很小,考虑爆搜。注意到直接枚举会枚举到分组顺序的全排列,所以可以强行嵌定大小关系去重。voiddfs(ints){if(s==n+1){for(inti=1;i<=t;......
  • NOI春季测试前模拟赛题解
    T312819命题工作直接容斥。总方案-一题出现四次-一题出现三次-一题出现两次。一题出现两次的情况略有不同,注意考虑周全。复杂度\(O(n)\)。codeT312891图上棋局有技巧的博弈论。如果当前点的所有出边均为先手必胜,那么当前点为先手必败。否则先手必胜。于是......
  • 题解 P2137 Gty的妹子树
    神奇的分块。假如没有\(2\)操作,我们可以直接用主席树解决。我们考虑将询问分块,每遍历完一块就将这一块内出现的所有修改更新。如果在块内,就把当前块之前的所有修改暴力算,当然只有修改的节点在询问的节点的子树内才会发生。具体的来说,我们可以用分块维护dfs序,并将块内的元素......
  • 题解 P4183 [USACO18JAN] Cow at Large P
    带有小trick的点分治。建议先做完弱化版再看。假如奶牛在\(u\),那么所需的最少农夫数为\(\sum\limits_{v\inson(u)}[dis(u,v)\geg_v][dis(u,fa_v)<g_{fa_v}]\)。其中\(dis(u,v)\)为\(u,v\)在树上的距离,\(g_u\)为\(u\)到离它最近的出入口的距离(BFS预处理),\(fa_u\)......
  • 题解 P9415 下楼
    不难推理出当初始绳长为\(len\),需要下降的距离为\(d\),并且满足\(d\lelen<2d\)时,最优的环套法可以只损失\(2d-len\)长度的绳子,留下\(2(len-d)\)的绳子。当\(2d\lelen\)时存在一种不损耗绳长的方法可以下到下一根钢管,即把整根绳子系成一个环,到达下面再剪断。正文:线......
  • 题解 P9437『XYGOI round1』一棵树
    换根DP。本蒟蒻最初没想到换根,把自己写自闭了...定义\(f_u\)为子树\(u\)中的每个结点走到\(u\)的贡献和,\(l_u\)为大于\(a_u\)的最小的\(10\)的幂次方数,\(sum_u\)为\(\sum\limits_{v\inson(u)}{f_v}\)。转移方程为:\(f_u=l_u\cdot\sum\limits_{v\inson(u)}{f_v}+......
  • 决策单调性优化DP 学习笔记 & P4767 [IOI2000] 邮局 题解
    0.题面题目描述高速公路旁边有一些村庄。高速公路表示为整数轴,每个村庄的位置用单个整数坐标标识。没有两个在同样地方的村庄。两个位置之间的距离是其整数坐标差的绝对值。邮局将建在一些,但不一定是所有的村庄中。为了建立邮局,应选择他们建造的位置,使每个村庄与其最近的邮局......
  • 题解 P7215
    点分治。考虑当前的分治重心的城市被完全联通。这可以用队列接解决。每次放入一种城市,就把那些城镇的父亲加入队列,如果存在城镇不在当前分治重心的联通块内,那么说明必定存在另一个分治重心能算到它,直接退出即可。剩下的和模板没有任何区别。复杂度\(O(n\logn)\)。code:#in......
  • 题解 P6329
    点分树模板题。是个神奇的算法。点分树就是将分治重心按照层级连边,每个节点父亲的联通块都包含了当前节点的联通块,且高度为\(\logn\)。可以解决不考虑树的形态的多次询问带修改的问题。对于这道题,我们可以在点分树的每个节点上记录两棵树状数组,分别与当前节点距离为\(k\)的......
  • 题解 P3345
    点分树。本题的核心问题在于不好直接确定补给站的位置。但是仔细思考后我们发现,对于当前节点,如果存在一个儿子的答案比它优,那么补给站一定在那个儿子的子树中。增量为\(w\times(sum_u-2\cdotsum_v)\)。当\(v\)优于\(u\)时,\(2\cdotsum_v>sum_u\)。如果\(v_2\)也满足,则......