CF1534G A New Beginning 题解

题目传送门

前置知识

曼哈顿距离与切比雪夫距离的相互转化

解法

将切比雪夫距离转换成曼哈顿距离,有新坐标为 \((\frac{x_{i}+y_{i}}{2},\frac{x_{i}-y_{i}}{2})\),因带一个 \(\frac{1}{2}\) 的常数不妨提出来得到 \((x_{i}'=x_{i}+y_{i},y_{i}'=x_{i}-y_{i})\) 最后统一乘起来。

此时切比雪夫坐标系里 \((x,y)\) 向上/右走分别对应曼哈顿坐标系里走到 \((x+1,y+1)/(x+1,y-1)\),即走路斜率对应 \(1/-1\)

将所有点按照横坐标排序后,设 \(f_{i,j}\) 表示处理第 \(i\) 个点时纵坐标为 \(j\) 时的最小花费,状态转移方程为 \(f_{i,j}=\min\limits_{k=j-(x_{i}'-x_{i-1}')}^{j+(x_{i}'-x_{i-1}')}\{ f_{i-1,k} \} +|j-y_{i}'|\),使用 Slope Trick 优化即可,做法和 [ABC217H] Snuketoon 基本类似。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
pair<ll,ll>a[800010];
priority_queue<ll,vector<ll>,less<ll> >l;
priority_queue<ll,vector<ll>,greater<ll> >r;
int main()
{
// #define Isaac
#ifdef Isaac
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif
	ll n,ans=0,x,y,lazyl=0,lazyr=0,i;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>x>>y;
		a[i].first=x+y;
		a[i].second=x-y;
		l.push(0);
		r.push(0);
	}
	sort(a+1,a+1+n);
	for(i=1;i<=n;i++)
	{
		lazyl-=a[i].first-a[i-1].first;
		lazyr+=a[i].first-a[i-1].first;
		if(a[i].second<l.top()+lazyl)
		{
			ans+=(l.top()+lazyl)-a[i].second;
			r.push(l.top()+lazyl-lazyr);
			l.pop();
			l.push(a[i].second-lazyl);
			l.push(a[i].second-lazyl);
		}
		else
		{
			if(a[i].second>r.top()+lazyr)
			{	
				ans+=a[i].second-(r.top()+lazyr);
				l.push(r.top()+lazyr-lazyl);
				r.pop();
				r.push(a[i].second-lazyr);
				r.push(a[i].second-lazyr);
			}
			else
			{
				l.push(a[i].second-lazyl);
				r.push(a[i].second-lazyr);
			}
		}
	}
	cout<<ans/2<<endl;
	return 0;
}
posted @ 2024-12-26 21:38  hzoi_Shadow  阅读(25)  评论(0编辑  收藏  举报
扩大
缩小