首页 > 其他分享 >[ARC181E] Min and Max at the edge

[ARC181E] Min and Max at the edge

时间:2024-08-08 14:29:06浏览次数:10  
标签:Node pii ARC181E return int Max void edge inline

My Blogs

[ARC181E] Min and Max at the edge

场上没人过的神题。(大概是搬运的官方题解)

先考虑如何 chk 一个图是否存在好生成树。观察好生成树的限制,发现其对于非树边的限制是在生成树上连接两点的路径有关。而 Kruskal 的证明就是对于每条非树边,其边权大于所有其路径上的树边,两者很像。

但是题目中的限制是点的限制,转到边上的想法是给点赋点权 \(X_i\),然后 \((u,v)\) 的边权为 \(|X_u-X_v|\)。考虑把 \(X\) 设成一个递增的序列,比如 \(X_i=10^i\),这样边权一定互不相同。

对于一棵好的生成树,设 \(S(u,v)\) 表示 \(u,v\) 之间的树上路径,则对于点 \(i\) 要求 \(\forall i\in S(u,v),X_u\leq X_i\leq X_v\)。而对于边 \((x,y)\),\(X_u\leq X_x,X_y\leq X_v\)。设其根据上述定义的边权是 \(w(x,y)=|X_x-X_y|\),则 \(\forall (x,y)\in S(u,v),w(x,y)<w(u,v)\)。这就证明了好的生成树一定是新图中的最小生成树。

因为可以构造出边权互不相同的情况,所以这也证明了好的生成树也是唯一的。跑出来这个图的最小生成树之后,检查每条非树边,如果都满足限制则该图是好的。

但是题目有多次询问,而且这个最小生成树也不是那么好求。不难发现其实图中定义的边权只需要满足 \(\forall i<j<k,w(i,j)<w(i,k)\) 并且 \(\forall i<j<k,w(i,k)>w(j,k)\) ,即满足区间包含单调性即可。

所以可以把边 \(w(u,v)\) 赋为 \(v\times(n+1)-u\),这样得到的生成树一定满足对于任意非树边 \((u,v)\),其路径上的最大值就是 \(v\)。原因是非树边 \((u,v)\) 路径上的边权应当都小于 \(w(u,v)\),所以如果存在大于 \(v\) 的点则一定不合法。而且因为是 \(-u\),所以合并两个连通块的时候,一边选择的较小的点会尽可能的大,这也满足路径上的最小值尽量是 \(u\)。

但是这样还是需要 chk 路径上点的最小值是否满足条件。可以再反着做一遍,\(w(u,v)=(n-u+1)\times(n+1)-(n-v+1)\),同理得这样求出来的东西的最小值一定合法,最大值尽量合法。因为已经证明了好的生成树唯一,所以判一下两棵树是否相同即可。

这样就将问题转化成了比较好的形式:删边求最小生成树,可以看成是找一条非树边 \((x,y)\) 满足 \(x\in \text{subtree}(i),y\notin \text{subtree(i)},w(x,y)\) 最小。转成 dfn 序之后可以看成是两个 3-side 矩形查最小值,可以扫描线线段树维护,复杂度是 \(\mathcal O(n\log n)\)。

int n,m,fa[200010];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
set<int> st;
inline void update(int id)
{
	auto it=st.find(id);
	if(it==st.end())st.insert(id);
	else st.erase(it);
}
int flag=1;
struct Node
{
	int x,y,z,t;
	Node(int X=0,int Y=0,int Z=0,int T=0){x=X,y=Y,z=Z,t=T;}
};
inline bool cmp1(Node x,Node y){return x.z<y.z;}
struct MST
{
	int cnt,head[200010],to[400010],nex[400010];
	int tot,siz[200010],dfn[200010];
	pii ans[200010];
	bool ins[200010];
	Node a[200010];
	vector<tup> L[200010],R[200010];
	vector<pair<int,pii>> ve[200010];
	inline pii get(pii x,pii y){return x.fi<y.fi?x:y;}
	struct{int l,r;pii v;}t[400010];
	#define ls(x) (t[x].l+t[x].r)
	#define rs(x) (ls(x)^1)
	void build(int p,int l,int r)
	{
		t[p]={l,r,mp(INF,0)};
		if(l==r)return; 
		int mid=l+((r-l)>>1);
		build(ls(p),l,mid),build(rs(p),mid+1,r);
	}
	void change(int p,int x,pii y)
	{
		t[p].v=get(t[p].v,y);
		if(t[p].l==t[p].r)return;
		change(ls(p)^(x>t[ls(p)].r),x,y);
	}
	pii ask(int p,int l,int r)
	{
		if(l<=t[p].l&&r>=t[p].r)return t[p].v;
		pii v=mp(INF,0);
		if(l<=t[ls(p)].r)v=get(v,ask(ls(p),l,r));
		if(r>t[ls(p)].r)v=get(v,ask(rs(p),l,r));
		return v;
	}
	inline void add(int x,int y){to[++cnt]=y,nex[cnt]=head[x],head[x]=cnt;}
	void dfs(int x,int Fa=0)
	{
		dfn[x]=++tot,siz[x]=1;
		for(int i=head[x];i;i=nex[i])if(to[i]!=Fa)
		dfs(to[i],x),siz[x]+=siz[to[i]];
	}
	inline void solve()
	{
		int x,y;
		for(int i=1;i<=n;++i)fa[i]=i;
		sort(a+1,a+1+m,cmp1);
		for(int i=1;i<=m;++i)
		{
			x=find(a[i].x),y=find(a[i].y),ans[i]=mp(INF,0ll);
			if(x==y)continue;
			ins[a[i].t]=1,update(a[i].t),fa[x]=y;
			add(a[i].x,a[i].y),add(a[i].y,a[i].x);
		}
		for(int i=2;i<=n;++i)flag&=find(i-1)==find(i);
		dfs(1),build(1,1,n);
		for(int i=1;i<=m;++i)
		{
			if(!ins[a[i].t])continue;
			x=dfn[a[i].x]<dfn[a[i].y]?a[i].y:a[i].x;
			L[dfn[x]-1].eb(tup(dfn[x],dfn[x]+siz[x]-1,a[i].t));
			R[dfn[x]+siz[x]].eb(tup(dfn[x],dfn[x]+siz[x]-1,a[i].t));
		}
		for(int i=1;i<=m;++i)if(!ins[a[i].t])
		ve[min(dfn[a[i].x],dfn[a[i].y])].eb(mp(max(dfn[a[i].x],dfn[a[i].y]),mp(a[i].z,a[i].t)));
		for(int i=1;i<=n;++i)
		{
			for(auto [x,y]:ve[i])change(1,x,y);
			for(auto [x,y,z]:L[i])ans[z]=get(ans[z],ask(1,x,y));
			ve[i].clear();
		}
		build(1,1,n);
		for(int i=1;i<=m;++i)if(!ins[a[i].t])
		ve[max(dfn[a[i].x],dfn[a[i].y])].eb(mp(min(dfn[a[i].x],dfn[a[i].y]),mp(a[i].z,a[i].t)));
		for(int i=n;i>=1;--i)
		{
			for(auto [x,y]:ve[i])change(1,x,y);
			for(auto [x,y,z]:R[i])ans[z]=get(ans[z],ask(1,x,y));
			ve[i].clear();
		}
	}
}t[2];
inline void mian()
{
	read(n,m);int x,y;
	for(int i=1;i<=m;++i)
	{
		read(x,y);
		if(x>y)swap(x,y);
		t[0].a[i]=Node(x,y,y*inf-x,i);
		t[1].a[i]=Node(x,y,(n-x+1)*inf-(n-y+1),i);
	}
	t[0].solve(),t[1].solve();
	if(!flag){for(int i=1;i<=m;++i)puts("No");return;}
	for(int i=1;i<=m;++i)
	{
		int fl=1;
		if(t[0].ins[i])fl&=t[0].ans[i].se!=0,update(i),update(t[0].ans[i].se);
		if(t[1].ins[i])fl&=t[1].ans[i].se!=0,update(i),update(t[1].ans[i].se);
		if(st.empty()&&fl)puts("Yes");else puts("No");
		if(t[0].ins[i])update(i),update(t[0].ans[i].se);
		if(t[1].ins[i])update(i),update(t[1].ans[i].se);
	}
}

标签:Node,pii,ARC181E,return,int,Max,void,edge,inline
From: https://www.cnblogs.com/WrongAnswer90/p/18348887

相关文章

  • 神经网络之卷积篇:详解更多边缘检测内容(More edge detection)
    详解更多边缘检测内容已经见识到用卷积运算实现垂直边缘检测,在本博客中,将看到如何区分正边和负边,这实际就是由亮到暗与由暗到亮的区别,也就是边缘的过渡。还能了解到其他类型的边缘检测以及如何去实现这些算法,而不要总想着去自己编写一个边缘检测程序。这张6×6的图片,左边较亮,而......
  • Python & Selenium 4 & Edge 浏览器 |加载个人浏览器配置文件(包括cookie)
    使用Selenium4,我尝试加载我的个人浏览器配置文件(包括cookie),以便它可以加载到我之前登录过的网站。我正在使用边缘浏览器。在测试我的代码片段时,它似乎没有加载我的浏览器配置文件,而是创建一个新的(配置文件1)。我已确保配置文件的路径是正确的。我的代码片段:edge_opt......
  • min-max 容斥
    前置知识请牢记二项式定理:\((a+b)^n=\sum\limits_{i=0}^{n}{\dbinom{n}{i}a^{n-i}b^i}\)或另外一种形式:\((a+1)^n=\sum\limits_{i=0}^{n}{\dbinom{n}{i}a^{n-i}}\)min-max容斥min-max容斥的主要思想是给每个子集分配一个系数(然后每个属于子集的\(a_i\)的系数加上该......
  • 【Oracle EBS R12】第三章 Primary Ledger Overview(英文版)
    PrimaryLedgerOverview1.TransactionComponentsTransactiondateTransactionDetailsTransactionAmount2.TransactiondateYearType:PeriodType:3.TransactionDetails4.TransactionAmount5.Summry3Cs4Cs6.PrimaryLedger(PL)1.TransactionComp......
  • 神经网络之卷积篇:详解边缘检测示例(Edge detection example)
    详解边缘检测示例卷积运算是卷积神经网络最基本的组成部分,使用边缘检测作为入门样例。在这个博客中,会看到卷积是如何进行运算的。在之前的博客中,说过神经网络的前几层是如何检测边缘的,然后,后面的层有可能检测到物体的部分区域,更靠后的一些层可能检测到完整的物体,这个例子中就是......
  • 机器学习中的两个重要函数--sigmoid和softmax
    机器学习中,常常见到两个函数名称:sigmoid和softmax。前者在神经网络中反复出现,也被称为神经元的激活函数;后者则出现在很多分类算法中,尤其是多分类的场景,用来判断哪种分类结果的概率更大。本文主要介绍这两个函数的定义,形态,在算法中的作用,以及两个函数之间的联系。1.sigmoid函数......
  • 抽象摘要—利用抽象摘要的能力获取关键信息,以增强长文本下游任务能力:Improving Long T
    ImprovingLongTextUnderstandingwithKnowledgeDistilledFromSummarizationModel利用从摘要模型中提炼的知识提高长文本理解能力paper:https://arxiv.org/abs/2405.04955github:本文做的是一个利用抽象摘要的能力,去提升下游长文本任务的能力,具体来说就是,利用......
  • 深度解读KubeEdge架构设计与边缘AI实践探索
    摘要:解读业界首个云原生边缘计算框架KubeEdge的架构设计,如何实现边云协同AI,将AI能力无缝下沉至边缘,让AI赋能边侧各行各业,构建智能、高效、自治的边缘计算新时代,共同探索智能边缘的新篇章。本文分享自华为云社区《DTSETechTalk|第63期:KubeEdge架构设计与边缘AI实践探索》,作者:......
  • 1388、STM32单片机心率(脉搏)MAX30102血氧体温检测阈值报警无线蓝牙远程(程序+原理图+
    毕设帮助、开题指导、技术解答(有偿)见文未 目录方案选择单片机的选择显示器选择方案一、设计功能二、实物图三、原理图四、程序源码五、PCB图六、proteus仿真程序流程图:原理图文字讲解:参考论文:资料包括:需要完整的资料可以点击下面的名片加下我,找我要资源压缩......
  • 最火的十大 Edge插件:安装指南、功能介绍及使用技巧
    最火的十大MicrosoftEdge插件:安装指南、功能介绍及使用技巧随着网络浏览需求的不断增加,浏览器插件变得越来越重要。MicrosoftEdge通过其丰富的插件生态系统,满足用户的多样化需求。本文将介绍十款在中国用户中最受欢迎的Edge插件,包括如何安装、使用及其主要功能和作用。这些......