首页 > 其他分享 >2024.7.26模拟赛8

2024.7.26模拟赛8

时间:2024-07-30 12:17:20浏览次数:15  
标签:26 struct 2024.7 int 连通 ST fa ans 模拟

模拟赛

抽象比赛,含金量最高的是题目背景?

好像还是连续的。。。

T1 Same Integers

题目背景

签到题,因为只有加操作,目标是将两个较小的数加成最大的。

根据差的奇偶判断能否加二得到,如果不能先加一调一下。(简单题,题解抽象一点也没事吧)

code
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e5+5;
LL a[3],ans;
int main()
{
	for(int i=0;i<3;i++) scanf("%lld",&a[i]);
	sort(a,a+3);
	int x=a[2]-a[0],y=a[2]-a[1];
	if((x&1) && (y&1)) ans=(x-1>>1)+(y-1>>1)+1;
	else if(x&1) ans=(y>>1)+(x+1>>1)+1;
	else if(y&1) ans=(x>>1)+(y+1>>1)+1;
	else ans=(x>>1)+(y>>1);
	printf("%lld\n",ans);
	return 0;
}

T2 Qpwoeirut and Vertices

首先要想到建立最小生成树,因为我们只在乎使某个连通块第一次被连通的边,后面再加边都可以忽略,所以最终建出的一定是一棵树。

然后考虑答案是什么,将边的编号赋成边权,那么使 \(u,v\) 连通的边权最大的边就是答案,也就是路径最大值。

使 \([l,r]\) 连通也很简单,就是使每两个相邻的节点连通,然后取区间最大值。

路径最大值可以用树剖 + ST 表,区间最值也用 \(ST\) 维护就好,发现是数据结构裸题。

正解是新科技:克鲁斯卡尔重构树

不同于最小生成树,克鲁斯卡尔重构树是对于每一条边建一个虚点,点权等于原边权,虚点向原边的两个端点所在连通块的代表点连边。

因为加边按顺序,所以这样重构的树(森林)从根到叶子的权值一定是单调不上升的,那么使两点连通的最小权值就是重构树离他们最近的祖先的点权

LCA + ST 表即可。

code(ST + ST)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int t;
int n,m,q;
struct K {int u,v,w;} k[N<<1];
inline bool cmp(const K &x,const K &y) {return x.w<y.w;}
int head[N],tot;
struct E {int u,v,w;} e[N<<1];
inline void add(int u,int v,int w) {e[++tot]={head[u],v,w}; head[u]=tot;}
struct BCJ
{
	int fa[N];
	inline void init() {for(int i=1;i<=n;i++) fa[i]=i;}
	inline int find(int x) {return x==fa[x]?x:fa[x]=find(fa[x]);}	
} bcj;

int dfn[N],dep[N],son[N],sz[N],cnt,rk[N],fa[N],top[N],a[N];

void dfs1(int u,int f)
{
	dep[u]=dep[f]+1; son[u]=-1; sz[u]=1; fa[u]=f;
	for(int i=head[u];i;i=e[i].u)
	{
		int v=e[i].v;
		if(v==f) continue;
		a[v]=e[i].w;
		dfs1(v,u);
		sz[u]+=sz[v];
		if(son[u]==-1||sz[son[u]]<sz[v]) son[u]=v;
	}
}
void dfs2(int u,int t)
{
	top[u]=t; dfn[u]=++cnt; rk[cnt]=u;
	if(son[u]==-1) return;
	dfs2(son[u],t);
	for(int i=head[u];i;i=e[i].u)
	{
		int v=e[i].v;
		if(v!=son[u]&&v!=fa[u]) dfs2(v,v);
	}
}
struct ST1
{
	int st[30][N];
	inline void bui()
	{
		for(int i=1;i<=n;i++) st[0][i]=a[rk[i]];
		for(int i=1;i<=25;i++) 
			for(int j=1;j+(1<<i)-1<=n;j++)
				st[i][j]=max(st[i-1][j],st[i-1][j+(1<<i-1)]);
	}
	inline int que(int l,int r)
	{
		int k=__lg(r-l+1);
		return max(st[k][l],st[k][r-(1<<k)+1]);
	}
} st;
int Que(int x,int y)
{
	int res=0;
	while(top[x]!=top[y])
	{
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		res=max(res,st.que(dfn[top[x]],dfn[x]));
		x=fa[top[x]];
	}
	if(x==y) return res;
	if(dep[x]>dep[y]) swap(x,y);
	res=max(res,st.que(dfn[x]+1,dfn[y]));
	return res;
}
struct ST2
{
	int st[30][N];
	inline void bui()
	{
		for(int i=1;i<n;i++) st[0][i]=Que(i,i+1);
		for(int i=1;i<=25;i++) 
			for(int j=1;j+(1<<i)-1<n;j++)
				st[i][j]=max(st[i-1][j],st[i-1][j+(1<<i-1)]);
	}
	inline int que(int l,int r)
	{
		int k=__lg(r-l+1);
		return max(st[k][l],st[k][r-(1<<k)+1]);
	}
} st2;
void init()
{
	cnt=0; tot=0;
	memset(head,0,sizeof(head));
}
int main()
{
//	freopen("lagrange3.in","r",stdin);
//	freopen("o1.out","w",stdout);
	scanf("%d",&t);
	while(t--) 
	{
		init();
		scanf("%d%d%d",&n,&m,&q);  bcj.init();
		for(int i=1;i<=m;i++)
		{
			int x,y; scanf("%d%d",&x,&y);
			k[i]={x,y,i};
		}
		for(int i=1;i<=m;i++)
		{
			int fx=bcj.find(k[i].u),fy=bcj.find(k[i].v);
			if(fx!=fy) bcj.fa[fx]=fy,add(k[i].u,k[i].v,k[i].w),add(k[i].v,k[i].u,k[i].w);
		}
		dfs1(1,0); dfs2(1,1);
		st.bui(); st2.bui();
		while(q--)
		{
			int x,y; scanf("%d%d",&x,&y);
			if(x==y) printf("0\n");
			else printf("%d\n",st2.que(x,y-1));
		}	
	}
	return 0;
}
code(重构树)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+5;
int t,q,n,m;
struct K {int u,v;} k[N];
int head[N],tot,num,w[N],fa[30][N],dep[N],a[N];
struct E {int u,v;} e[N<<1];
inline void add(int u,int v) {e[++tot]={head[u],v}; head[u]=tot;}
struct BCJ
{
	int fa[N];
	void bui()
	{
		for(int i=1;i<=(n<<1);i++) fa[i]=i;
	}
	inline int find(int x)
	{
		if(x!=fa[x]) fa[x]=find(fa[x]);
		return fa[x];
	}
} bcj;
void dfs(int u,int f)
{
	dep[u]=dep[f]+1; fa[0][u]=f;
	for(int i=1;i<=20;i++) fa[i][u]=fa[i-1][fa[i-1][u]];
	for(int i=head[u];i;i=e[i].u)
	{
		int v=e[i].v; if(v==f) continue;
		dfs(v,u);
	}
}
int lca(int x,int y)
{
	if(dep[x]<dep[y]) swap(x,y);
	for(int i=20;i>=0;i--) if(dep[fa[i][x]]>=dep[y]) x=fa[i][x];
	if(x==y) return x;
	for(int i=20;i>=0;i--) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
	return fa[0][x];
}
struct ST
{
	int st[20][N];
	void bui()
	{
		for(int i=1;i<n;i++) st[0][i]=a[i];
		for(int i=1;i<=20;i++)
			for(int j=1;j<n;j++)
				st[i][j]=max(st[i-1][j],st[i-1][j+(1<<i-1)]);
	}
	int que(int l,int r)
	{
		int k=__lg(r-l+1);
		return max(st[k][l],st[k][r-(1<<k)+1]);
	}
} st;
int main()
{
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d%d",&n,&m,&q); tot=0,num=n;
		for(int i=1;i<=m;i++) scanf("%d%d",&k[i].u,&k[i].v);
		for(int i=1;i<=n<<1;i++)
		{
			bcj.fa[i]=i; head[i]=0; dep[i]=0;
		}
		for(int i=1;i<=m;i++)
		{
			int fx=bcj.find(k[i].u),fy=bcj.find(k[i].v);
			if(fx==fy) continue;
			bcj.fa[fx]=bcj.fa[fy]=++num; w[num]=i;
			add(num,fx); add(num,fy);
		}
		for(int i=num;i>=n+1;i--)
			if(!dep[i]) dfs(i,0);
		for(int i=1;i<n;i++)
		{
			int d=lca(i,i+1);
			a[i]=w[d];
		}
		st.bui();
		while(q--)
		{
			int l,r; scanf("%d%d",&l,&r);
			if(l==r) printf("%d ",0);
			else printf("%d ",st.que(l,r-1));
		}
		printf("\n");
	}
	return 0;
}

标签:26,struct,2024.7,int,连通,ST,fa,ans,模拟
From: https://www.cnblogs.com/ppllxx-9G/p/18332102

相关文章

  • 2024.7.25模拟赛7
    模拟赛疯狂补题解/改题中。。。T1[Permutations&Primes](未找到)构造一个\(1-n\)的序列,使所有区间中\(mex\)为质数的最多。感觉题不是很好。结论是:\(1\)放中间,\(2,3\)放两边。打标找规律,感性证明也挺显然的。nocodeT2SpreadofInformation首先看道典题:消......
  • [OI] 模拟退火
    模拟退火是一种适合求样本点较大的多峰函数极值的方法.模拟退火有几个参数:初始温度(\(T_{0}\)),终止温度(\(T_{e}\))和降温参数\(d\),具体地,模拟退火是让每次的当前温度\(T\)变为\(d\timesT\),直到终止,因此\(T_{e}\)应为一个很接近\(0\)的正数,\(d\)应该为一个很接近\(1\)的......
  • 有什么方法可以将模拟对象伪装成 Qt 方法参数中可接受的 PyQt 对象吗?
    这是MRE。您需要pytest安装...事实上pytest-qt不会造成任何伤害。importsys,pytestfromPyQt5importQtWidgetsfromunittestimportmockclassMyLineEdit(QtWidgets.QLineEdit):def__init__(self,parent):super().__init__(paren......
  • mysql的MHA以及故障模拟
    目录MHA概念MHA的组件MHA的特点实验:搭建完成MHA的架构实验:主备切换实验结果实验:故障切换实验:故障恢复MHA概念MHA:高可用模式下的故障切换,基于主从复制。它解决的是单点故障和主从复制不能切换的问题。它至少需要3台。故障切换过程0-30秒。它能根据VIP地址所在的主机......
  • 2024年7.26-7.29学习总结/day29-32
    2024年7.26-7.29学习总结部署上线乐泡泡用户中心项目开坑伙伴匹配系统项目刷牛客刷leetcode部署上线​ 域名备案已申请,但是还没通过,让我周三再申请一次,难受。系统上线之后查询系统还有点bug不过别的功能基本上没有问题。这个项目很简单,就算是从0到1走通了全栈开发的一......
  • 「模拟赛」暑期集训CSP提高模拟10(7.28)
    \(145pts,Rank10\),众数分。数学专题模拟赛%%%总结写前面:1.线性递推式复杂度过大考虑矩阵快速幂优化;2.T1长时间切不了就先跳,先把所有题看一遍,拿分为主。赛时记录正常开T1,期望数学题,大概读懂了,手模下小样例,模了一遍又一遍,“我并不认为样例是对的”,跳了(很正确的决定)。......
  • 2024.7.29 test
    A给出\(n,m\),你要求对于所有长度为\(n\)的非负整数序列\(A,B\)中,满足\(\sumA_i=\sumB_i=m\),求\((\sum|A_i-B_i|)^2\)的总和。\(n\le500,m\le10^5\)。首先我们发现\(\sum(A_i-B_i)=0\),所以\(\sum|A_i-B_i|=2\sum_{A_i<B_i}B_i-A_i\)。我们把序列分为两部分,一......
  • 暑假集训csp提高模拟11
    赛时rank9,T1100,T2100,T30,T40update:赛后T1被hack了,成了99,死因没有记忆化挂成了rank10我又要挂分了。T3暴力挂了?话说jjdw和k8啥时候回来。T1Fate签到题,最短路板子。考虑一个点\(a\),其最短路前驱节点为\(b\),前驱结点组成的集合为\(B\),其次短路的前驱节点为......
  • 暑假集训CSP提高模拟11
    A.Fate求次短路方案数.这题有点小水了,好像之前做过.具体的方案显然是DP,考虑枚举当前每一个路径长度,假如比最短路更优则覆盖最短路,之前的最短路用来覆盖次短路.否则如果比次短路更优,则直接覆盖次短路.方案数的话考虑一样的方法维护,只是在遇到相等的路径长时使方案数加一即可.......
  • 暑假集训CSP提高模拟11
    暑假集训CSP提高模拟11组题人:@KafuuChinocpp\(T1\)P152.Fate\(24pts\)强化版:HDU1688Sightseeing设\(dis_{i,0/1}\)表示从\(s\)到\(i\)的最短路/次短路长度,\(f_{i,0/1}\)表示从\(s\)到\(i\)的最短路/次短路条数。\(dijkstra\)过程中按照路径长度与......