首页 > 其他分享 >CF1842E Tenzing and Triangle 题解

CF1842E Tenzing and Triangle 题解

时间:2023-12-11 12:33:34浏览次数:20  
标签:Triangle int 题解 mn tree mid add Tenzing id

题意不多赘述。

思路

如果两个所选的三角形有重合部分的话,那么这种情况肯定是不会出现的。因为如果把这两个三角形合成一个大三角形的话,不仅覆盖面积会增大,而且花费的代价还不会多。

于是我们可以想到用 dp 来解决,设 \(dp_{i}\) 表示删完横坐标为 \(0\) 到 \(i\) 中的点的最小代价,很容易得到状态转移方程:\(dp_{i}=\min(dp_{j}+(i-j-1)\times A+cost)\)。这里的 \(cost\) 指的是所有满足 \(j<x\le i,1\le y<k-i\) 的条件的点,因为只有这些点没有被当前所选的这个三角形所包含,所以需要加上这些点的代价。但是这个方程转移的时间复杂度是 \(O(n^{2})\) 的,所以还需要优化。

我们可以发现一些性质,首先方程中的 \(A\times(i-j-1)\) 一定是递减的,而 \(cost\) 值的变化也有一些规律。从 \(i\) 变到 \(i+1\) 的过程中,需要加上满足 \(x=i\) 的点的代价,减去满足 \(y=k-i\) 的点的代价,其余的点不会变化。所以我们发现每一次从 \(i\) 变为 \(i+1\) 我们都可以只修改之前所有 \(A\) 和 \(cost\) 的值就行了,每一次的值就是前面所有数的最小值,而这两个操作都可以用线段树来维护,时间复杂度 \(O(n \log n)\)。注意线段树维护的每一个 \(j\) 的值已经是 \(dp_{j}+(i-j-1)\times A+cost\) 了,所以直接查询最小值就可以了。

注意因为坐标轴的最小值为 \(0\),所以我们还需要维护一个下标为 \(-1\) 的值,这个值代表前面还什么都没有选时的代价。

Code

#include<bits/stdc++.h>
using namespace std; 
#define int long long
#define inf 0x3f
#define inf_db 127
#define ls id << 1
#define rs id << 1 | 1
#define re register
#define endl '\n'
typedef pair <int,int> pii;
const int MAXN = 1e6 + 10;
int n,x,y,c,cost[MAXN],k,A,dp[MAXN];
struct SegmentTree{int id,l,r,mn,add;}tree[MAXN];
inline void Pushup(int id){tree[id].mn = min(tree[ls].mn,tree[rs].mn);}
inline void Build(int id,int l,int r)
{
	tree[id].l = l,tree[id].r = r;
	if(l == r){tree[id].mn = 0;return;}
	int mid = (l + r) >> 1;
	Build(ls,l,mid),Build(rs,mid + 1,r);
}
inline void Pushdown(int id)
{
	if(tree[id].add == 0) return;
	tree[ls].mn += tree[id].add,tree[ls].add += tree[id].add;
	tree[rs].mn += tree[id].add,tree[rs].add += tree[id].add;
	tree[id].add = 0;
}
inline void Add(int id,int l,int r,int a,int b,int c)
{
	if(a <= l && b >= r)
	{
		tree[id].mn += c;
		tree[id].add += c;
		return;
	}
	Pushdown(id);
	int mid = (l + r) >> 1;
	if(a <= mid) Add(ls,l,mid,a,b,c);
	if(b > mid) Add(rs,mid + 1,r,a,b,c);
	Pushup(id);
}
inline int Query(int id,int l,int r,int a,int b)
{
	if(a <= l && b >= r) return tree[id].mn;
	Pushdown(id);
	int mid = (l + r) >> 1,res = 1e18;
	if(a <= mid) res = min(res,Query(ls,l,mid,a,b));
	if(b > mid) res = min(res,Query(rs,mid + 1,r,a,b));
	return res;
}
std::vector <pii> a[MAXN];
signed main()
{
	cin >> n >> k >> A;
	Build(1,-1,k);
	for(int i = 1;i <= n;i++)
	{
		cin >> x >> y >> c;
		a[y].emplace_back(x,c);
		if(x + y != k) cost[x] += c;
	}
	for(int i = 0;i <= k;i++)
	{
		for(int j = 0;j < a[k - i].size();j++) Add(1,-1,k,-1,a[k - i][j].first - 1,-a[k - i][j].second);
		Add(1,-1,k,-1,i - 1,cost[i]);
		if(i != 0) Add(1,-1,k,-1,i - 2,A);
		dp[i] = Query(1,-1,k,-1,i - 1),Add(1,-1,k,i,i,dp[i]);
	}
	cout << dp[k]; 
	return 0;
}		

标签:Triangle,int,题解,mn,tree,mid,add,Tenzing,id
From: https://www.cnblogs.com/Creeperl/p/17894121.html

相关文章

  • [ABC304Ex] Constrained Topological Sort 题解
    题意给定一张有向图\(G\),有\(n\)个点和\(m\)条边,问是否存在一种拓扑序的排列\(P\)使得\(l_{i}\lep_{i}\ler_{i}\)。思路首先对于一条边\(u\tov\),如果限制满足\(r_{v}\ler_{u}\)或者\(l_{v}\gel_{u}\)的话,那么这个限制其实是不完全正确的。因为最终的序列......
  • 【题解】AtCoder abc322_f Random Update Query
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_f容易发现,对于一个位置$i$,$A_i$的最终值是由对$i$的最后一次赋值操作决定的;因此,将所有操作按时间顺序倒过来考虑,则由第$j$次操作决定$A_i$最终值的概率为"在第$(j+1)$~$m$次操作中没有修改过$i$的概率"与"第......
  • 【题解】AtCoder abc332_g Not Too Many Balls
    传送门:https://atcoder.jp/contests/abc332/tasks/abc332_g看完题,第一眼反应为最大流。建模方式为:以颜色为左部点,盒子为右部点,源点$S$向颜色$i$连一条容量为$A_i$的边,盒子$j$向汇点$T$连一条容量为$B_j$的边,颜色$i$向盒子$j$连一条容量为$ij$的边;在这张图......
  • AT_cf17_final_j Tree MST 题解
    题意:给定一颗\(n\)个点的树,点\(i\)有权值\(a_{i}\),边有边权。现在有另外一个完全图,两点之间的边权为树上两点之间的距离加上树上两点的点权,求这张完全图的最小生成树。首先有一个很显然的暴力,把完全图中每两点之间的边权算出来,然后跑一边最小生成树,时间复杂度\(O(n^{2}\lo......
  • P7735 [NOI2021] 轻重边 题解
    是一道树剖好题,之前听lsl讲过一点,于是很快就做出来了。题意:有一个\(n\)个节点的树,最开始的时候所有边都是轻边,维护两个操作:操作一:将\(u\)到\(v\)的路径中经过的所有点的邻边变为轻边,再将这条路径上的边变为重边。操作二:求出\(u\)到\(v\)这条路径上有多少条重边......
  • 小程序建立用户与数据的联系问题解决方案
    在小程序中建立用户与数据的联系是一个常见的问题,在本文中提供了一个解决方案。这个解决方案包括几个关键步骤。首先,需要通过用户登录功能实现用户的身份识别,并获取到用户的唯一标识符。接着,需要在后台数据库中创建一个用户表,用于存储用户的基本信息和与之相关联的数据。在这个表中......
  • ARC169 B Subsegments with Small Sums 题解
    LinkARC169BSubsegmentswithSmallSumsQuestion\(x\)是一个序列,定义\(f(x)\)为把序列\(x\)切成几段,每段的和不能超过\(S\)的最小段数给出序列\(A=(A_1,A_2,\cdots,A_N)\)求:\[\sum_{1\lel\leN}f((A_l,A_{l+1},\cdots,A_r))\]Question先考虑一个结论,\(x\)为......
  • P9915 「RiOI-03」3-2 题解
    更好的阅读这是一道找规律的题目。因为我个人习惯,以下部分使用从\(1\)开始的下标讲述。首先我们以\(1\)来说:发现在第\(x\)行\(y\)列的连通块是可以直接连到第\(1\)列的,所以很容易可以得出\(1\)到\(y\)列的连通块数量是\(2^y-1\)。接着,我们考虑再后面的情况:......
  • 常见问题解决 --- pip SSLEOFError
    问题C:\Users\Administrator\Desktop>pipinstallscapy-ihttp://pypi.douban.com/simple--trusted-hostpypi.douban.comLookinginindexes:http://pypi.douban.com/simpleWARNING:Retrying(Retry(total=4,connect=None,read=None,redirect=None,status=None......
  • 【题解】CQOI2017 - 小 Q 的表格
    【题解】CQOI2017-小Q的表格https://www.luogu.com.cn/problem/P3700首先考虑题面给的两个式子。由式二可以得到:\[\dfrac{f(a,a+b)}{a(a+b)}=\dfrac{f(a,b)}{ab}\]发现这个很像辗转相除,可得\[\dfrac{f(a,b)}{ab}=\dfrac{f(a,a\bmodb)}{a(a\bmodb)}\]然后由式一转换,最......