洛谷P5114 八月脸(边分治+闵可夫斯基和)

本文深入探讨了边分治与闵可夫斯基和算法在解决复杂问题中的应用,通过实例讲解了如何利用这两种算法优化计算过程,特别是在处理图形几何和数据结构问题上的高效解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门
边分治+闵可夫斯基和即可(注意要处理lca的情况
简单易懂,我们赢了(滑稽保命
代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	bool f=1;
	char ch=gc();
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
typedef long long ll;
typedef pair<int,int> pii;
const int N=5e5+5,inf=0x3f3f3f3f;
vector<int>g[N],Son[N],e[N];
int va[N],vb[N],typ[N],n,m,qr,siz[N],all,Fa[N],ft[N];
pii Rt;
struct pot{
	ll x,y;
	pot(ll x=0,ll y=0):x(x),y(y){}
	friend inline pot operator+(const pot&a,const pot&b){return pot(a.x+b.x,a.y+b.y);}
	friend inline pot operator-(const pot&a,const pot&b){return pot(a.x-b.x,a.y-b.y);}
	friend inline ll operator^(const pot&a,const pot&b){return a.x*b.y-a.y*b.x;}
    friend inline bool operator<(const pot&a,const pot&b){return a.x^b.x?a.x<b.x:a.y<b.y;}
};
vector<pot>ptt,pt[2][2];
bool vis[N];
inline void graham(vector<pot>&a){
	static int top=0,q[N],n;
	top=0,n=a.size()-1;
    sort(a.begin(),a.end());
	for(ri i=0;i<=n;++i){
		while(top>1&&((a[i]-a[q[top]])^(a[q[top]]-a[q[top-1]]))<=0)--top;
		q[++top]=i;
	}
	for(ri i=1;i<=top;++i)a[i-1]=a[q[i]];
	a.resize(top);
}
inline void Msum(vector<pot>a,vector<pot>b){
    if(!a.size()||!b.size())return;
	graham(a),graham(b);
	ptt.push_back(a[0]+b[0]);
	int n=a.size()-1,m=b.size()-1,p1=0,p2=0;
	pot ta,tb;
	while(p1<n&&p2<m){
		ta=a[p1+1]-a[p1],tb=b[p2+1]-b[p2];
		if((ta^tb)<=0)ptt.push_back(ptt.back()+ta),++p1;
		else ptt.push_back(ptt.back()+tb),++p2;
	}
	while(p1<n)ptt.push_back(ptt.back()+a[p1+1]-a[p1]),++p1;
	while(p2<m)ptt.push_back(ptt.back()+b[p2+1]-b[p2]),++p2;
}
void dfs(int p,int fa){
	for(ri i=0,v;i<g[p].size();++i){
		if((v=g[p][i])==fa)continue;
		dfs(v,p),Son[p].push_back(v);
	}
}
bool chs[N];
void dfs1(int p,int fa,int sz){
	siz[p]=1;
	for(ri t,i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||vis[v])continue;
		dfs1(v,p,sz),siz[p]+=siz[v];
		if((t=max(siz[v],sz-siz[v]))<all)all=t,Rt=pii(p,v);
	}
}
void dfs2(int p,int fa,pot dis,int op){
	bool ff=chs[ft[p]];
	if(!ff)chs[ft[p]]=1,dis=dis+pot(va[ft[p]],vb[ft[p]]);
	if(~typ[p])pt[op][typ[p]].push_back(dis);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||vis[v])continue;
		dfs2(v,p,dis,op);
	}
	chs[ft[p]]=ff;
}
void Dfs(int p,int sz){
	all=inf;
	dfs1(p,0,sz);
	if(all==inf)return;
	int a=Rt.fi,b=Rt.se;
	for(ri i=0;i<2;++i)for(ri j=0;j<2;++j)pt[i][j].clear();
    if(Fa[a]==b){
		chs[ft[b]]=1;
        dfs2(a,b,pot(0,0),0);
        dfs2(b,a,pot(va[ft[b]],vb[ft[b]]),1);
		chs[ft[b]]=0;
    }
    else{
		chs[ft[a]]=1;
        dfs2(b,a,pot(0,0),1);
		dfs2(a,b,pot(va[ft[a]],vb[ft[a]]),0);
		chs[ft[a]]=0;
    }
    Msum(pt[0][0],pt[1][1]),Msum(pt[0][1],pt[1][0]);
	vis[b]=1,Dfs(a,sz-siz[b]),vis[b]=0;
	vis[a]=1,Dfs(b,siz[b]),vis[a]=0;
}
void rebuild(){
	for(ri v1,v2,i=1,up;i<=m;++i){
		up=Son[i].size();
		if(up<3){
			for(ri j=0;j<up;++j){
				e[i].push_back(Son[i][j]);
				e[Son[i][j]].push_back(i);
                Fa[Son[i][j]]=i;
			}
		}
		else{
			typ[v1=++m]=-1;
			e[i].push_back(v1),e[v1].push_back(i);
            Fa[v1]=i,ft[v1]=ft[i];
			typ[v2=++m]=-1;
			e[i].push_back(v2),e[v2].push_back(i);
            Fa[v2]=i,ft[v2]=ft[i];
			for(ri j=0;j<up;++j)Son[j&1?v1:v2].push_back(Son[i][j]);
		}
	}
}
inline ll query(int k){
	int n=ptt.size()-1;
	ll ret=-1e18;
	pot t=pot(-1,k);
	if(ptt.size()<=10){
		for(ri i=0;i<=n;++i)ret=max(ret,(ptt[i]^t));
		return ret;
	}
	if(((ptt[1]-ptt[0])^t)<=0)return ptt[0]^t;
	if(((ptt[n]-ptt[n-1])^t)>=0)return ptt[n]^t;
	int L=1,R=n-1;
	while(L<=R){
		int mid=(L+R)>>1;
		bool f1=((ptt[mid+1]-ptt[mid])^t)<=0,f2=((ptt[mid]-ptt[mid-1])^t)<=0;
		if(f1^f2)return ptt[mid]^t;
		if(f1&&f2)R=mid-1;
		else L=mid+1;
	}
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
    freopen("lx.out","w",stdout);
	#endif
	n=m=read(),qr=read();
	for(ri i=1;i<=n;++i)va[i]=read();
	for(ri i=1;i<=n;++i)vb[i]=read();
	for(ri i=1;i<=n;++i)typ[i]=read(),ft[i]=i;
	for(ri i=1,u,v;i<n;++i){
		u=read(),v=read();
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,0);
	rebuild();
    Dfs(1,m);
	graham(ptt);
	while(qr--)cout<<query(read())<<'\n';
	return 0;
}
资源下载链接为: https://pan.quark.cn/s/d9ef5828b597 在本文中,我们将探讨如何通过 Vue.js 实现一个带有动画效果的“回到顶部”功能。Vue.js 是一款用于构建用户界面的流行 JavaScript 框架,其组件化响应式设计让实现这种交互功能变得十分便捷。 首先,我们来分析 HTML 代码。在这个示例中,存在一个 ID 为 back-to-top 的 div 元素,其中包含两个 span 标签,分别显示“回到”“顶部”文字。该 div 元素绑定了 Vue.js 的 @click 事件处理器 backToTop,用于处理点击事件,同时还绑定了 v-show 指令来控制按钮的显示与隐藏。v-cloak 指令的作用是在 Vue 实例渲染完成之前隐藏该元素,避免出现闪烁现象。 CSS 部分(backTop.css)主要负责样式设计。它首先清除了一些默认的边距填充,对 html body 进行了全屏布局,并设置了相对定位。.back-to-top 类则定义了“回到顶部”按钮的样式,包括其位置、圆角、阴影、填充以及悬停时背景颜色的变化。此外,与 v-cloak 相关的 CSS 确保在 Vue 实例加载过程中隐藏该元素。每个 .page 类代表一个页面,每个页面的高度设置为 400px,用于模拟多页面的滚动效果。 接下来是 JavaScript 部分(backTop.js)。在这里,我们创建了一个 Vue 实例。实例的 el 属性指定 Vue 将挂载到的 DOM 元素(#back-to-top)。data 对象中包含三个属性:backTopShow 用于控制按钮的显示状态;backTopAllow 用于防止用户快速连续点击;backSeconds 定义了回到顶部所需的时间;showPx 则规定了滚动多少像素后显示“回到顶部”按钮。 在 V
### 闵可夫斯基的概念与应用 #### 什么是闵可夫斯基闵可夫斯基(Minkowski Sum),是一种定义在欧几里得空间中的运算,用于描述两个集合 \( A \) \( B \) 的组合方式。其形式化定义为: \[ A + B = \{ a + b : a \in A, b \in B \} \] 这意味着,\( A \) 中的每一个点都加上 \( B \) 中的每一个点,最终形成一个新的点集。 这种概念广泛应用于计算几何领域,特别是在处理多边形的操作时具有重要意义[^1]。 --- #### 如何通过闵可夫斯基判断两图形是否发生碰撞? 当讨论两个物体之间的相对运动或静态位置关系时,可以通过构建它们的 **闵可夫斯基差** 来简化问题。尽管严格意义上只有 “闵可夫斯基”,但在某些场景下,“闵可夫斯基差” 被视为一种特殊的闵可夫斯基操作——即将其中一个对象的所有顶点取反后再参与运算[^3]。 例如,在检测两个凸多边形是否有重叠区域的过程中,可以先生成这两个多边形对应的闵可夫斯基差,随后检查该差集中是否存在某个子结构能够完全包裹住原点。如果确实如此,则表明原始输入的两个多边形已经相互接触或者穿插在一起;反之则未发生任何干涉现象[^2]。 --- #### 实际应用场景举例 以下是几个典型的应用实例说明了如何利用这一理论解决实际工程难题: 1. **机器人路径规划**: 假设有一个移动平台需要避开障碍物前进至目标地点。此时可以把机器人的外形轮廓以及周围环境里的固定阻碍物分别表示成若干离散化的简单几何体(比如矩形),接着运用上述方法快速判定哪些候选轨迹可能会撞上东西并及时调整方向。 2. **游戏开发中的物理引擎设计**: 类似于前面提到的例子,在实时渲染的游戏世界里面经常需要用到类似的算法来模拟真实的动态效果,像车辆撞击墙壁反弹之类的交互行为都可以基于此原理实现自动化处理逻辑。 3. **建筑设计辅助工具软件功能扩展**: 当建筑师试图评估不同楼层之间楼梯间布局合理性的时候,同样可以用这种方式分析各个独立部分是否会因为尺寸误差等原因而导致不必要的冲突矛盾等问题出现。 --- #### 关键技术细节探讨 为了更高效地完成以上任务,还需要掌握一些额外的技术要点: - 使用支持函数(Support Function): 这种技巧允许我们在不显式枚举全部潜在候选项的前提下逐步逼近最优解的方向迭代寻找满足条件的关键特征点序列直至收敛为止. - 判断点相对于任意复杂边界的关系状态: 对于此类基础查询需求而言,通常会采用射线法(Ray Casting Algorithm)或者其他相似策略来进行精确分类标记[^4]. - 高效求解大规模数据集下的整体形态特性: 如果涉及的对象数量较多而且彼此关联紧密的话,那么直接逐一对比显然效率低下不可接受。这时候就需要引入分治思想或者是借助FFT变换加速卷积过程等方式优化性能表现[^5]. ```python def minkowski_sum(A, B): result = [] for a in A: for b in B: result.append((a[0]+b[0], a[1]+b[1])) return result ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值