首页 > 其他分享 >暑假集训CSP提高模拟8

暑假集训CSP提高模拟8

时间:2024-07-26 20:06:24浏览次数:5  
标签:return cout int mid 集训 fa 暑假 ans CSP

T1
image

点击查看代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll a[5];
int main()
{
	cin>>a[1]>>a[2]>>a[3];
	sort(a+1,a+3+1);
	ll ans=(a[3]-a[1])/2+(a[3]-a[2])/2;
	a[1]+=(a[3]-a[1])/2*2;a[2]+=(a[3]-a[2])/2*2;
	if(a[1]==a[2]&&a[1]!=a[3])ans++;
	else if(a[1]!=a[2])ans+=2;
	cout<<ans;
	return 0;
}

T2
赛时想法是维护\(m\)个并查集,二分答案,然后比较祖先是否相同,\(O(mlogn+qmlogn)\)的复杂度,而且内存开不下,只拿\(20pts\)

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N = 1e5+5;
vector <int> fa[N*2];
vector <pair<int,int>> G;
int n,m,q;
inline int find(int u,int id)
{
	if(fa[id][u]!=u)fa[id][u]=find(fa[id][u],id);
	return fa[id][u];
}
inline bool check(int mid,int L,int R)
{
	int c=find(L,mid);
//	cout<<c<<endl;
	for(int i=L+1;i<=R;i++)
	{
		if(find(i,mid)!=c)return 0;
	}
	
	return 1;
}
inline int fen(int l,int r,int L,int R)
{
	int ans=0;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid,L,R))
		{
			ans=mid;
			r=mid-1;
		}else
		{
			l=mid+1;
		}
	}
	return ans;
}
inline void work1()
{
	int u,v;
	for(int i=0;i<=m;i++)fa[i].resize(n+1);
	for(int i=1;i<=n;i++)fa[0][i]=i;
	for(int i=1;i<=m;i++)
	{
		copy(fa[i-1].begin(),fa[i-1].end(),fa[i].begin());
		u=G[i].first,v=G[i].second;
		int fu=find(u,i),fv=find(v,i);
		if(fu!=fv)fa[i][fu]=fv;
	}
	int l,r;
	while(q--)
	{
		cin>>l>>r;
		if(l==r)cout<<0<<endl;
		else
		{
			cout<<fen(1,m,l,r)<<endl;
		}
	}
}
int w2(int l,int r,int L,int R)
{
	int ans=0;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(0,L,R))
		{
			ans=mid;
			r=mid-1;
		}else
		{
			l=mid+1;
		}
	}
	return ans;
}
void work2()
{
	int l,r;
	cin>>l>>r;
//	cout<<l<<" "<<r<<endl;
	int u,v;
	fa[0].resize(n+1);
	for(int i=1;i<=n;i++)fa[0][i]=i;
	for(int i=1;i<=m;i++)
	{
		u=G[i].first,v=G[i].second;
		int fu=find(u,0),fv=find(v,0);
		if(fu!=fv)fa[0][fu]=fv;
//		if(i>=r-l+1)
//		{
		if(check(0,l,r))
		{
			cout<<i<<endl;
			break;
		}
//		}
//		cout<<fu<<" "<<fv<<endl;
	}	
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);	
//	freopen("lagrange2.in","r",stdin);
	
	cin>>n>>m>>q;int u,v;G.pb({0,0});
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v;G.pb({u,v});
	}
	if(n<=100&&m<=100)
	{
		work1();
	}else if(q==1)
	{
//		cout<<"*****"<<endl;
		work2();
	}else
	{
		work1();
	}
	return 0;
}

暴力部分分可以拿到\(35pts\)

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N = 1e5+5;
vector <pair<int,int>> edge[N];
int n,m,q;bool vis[N];
void dfs(int u,int fa,int lim)
{
	vis[u]=1;
//	cout<<u<<endl;
	for(int i=0;i<edge[u].size();i++)
	{
		int to=edge[u][i].first,id=edge[u][i].second;
		if(id>lim)continue;
		if(to==fa||vis[to])continue;
//		cout<<to<<" "<<u<<" "<<lim<<endl;
		dfs(to,u,lim);
	}
}
bool check(int mid,int L,int R)
{
//	cout<<"CHECK"<<mid<<" "<<L<<" "<<R<<endl;
	
//	for(int i=L;i<=R;i++)vis[i]=0;
	memset(vis,0,sizeof vis);
	dfs(L,0,mid);
	for(int i=L;i<=R;i++)
	{
		if(!vis[i])return 0;
	}
	return 1;
}
int fen(int l,int r,int L,int R)
{
	int ans=0;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid,L,R))
		{
			ans=mid;
			r=mid-1;
		}else
		{
			l=mid+1;
		}
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);	
//	freopen("lagrange2.in","r",stdin);
	
	cin>>n>>m>>q;int u,v;
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v;
//		cout<<"***"<<u<<" "<<v<<endl;
		edge[u].pb({v,i});
		edge[v].pb({u,i});
	}
	int l,r;
	while(q--)
	{
		cin>>l>>r;
		if(l==r)cout<<0<<endl;
		else
		{
			cout<<fen(1,m,l,r)<<endl;
		}
	}
	return 0;
}

image

正解,\(Kruskal\)重构树,边的编号即为边权,我考试并查集想到了,\(kruskal\)没想到,哎
image
image

其实\(m==n-1\)就是在启发树的时候如何处理,
我们想要知道\([l,r]\)即为\(l->r\)的边权最大值,相当于\(max(l->l+1,l+1->l+2,...,r-1->r)\),所以我们可以预处理出全部的\((i,i+1)\),然后查询可以用线段树,\(ST表\),查询\([l,r-1]\)即可

点击查看代码
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
using namespace std;
const int N = 1e5+5;
//vector <pair<int,int>> edge[N];
int n,m,q,fa[N*2],f[N*2][25],now,st[N][25],val[N*3],dep[N*2];bool vis[N*3];
struct Node{int u,v,w;};vector <Node> G ;
//bool cmp(Node a,Node b){return a.w<b.w;}
vector <int> edge[N*2];
int find(int u)
{
	if(fa[u]!=u)fa[u]=find(fa[u]);
	return fa[u];
}
void dfs(int u,int fa)
{
	vis[u]=1;
	dep[u]=dep[fa]+1;
	f[u][0]=fa;
	for(int j=1;j<=20;j++)
		f[u][j]=f[f[u][j-1]][j-1];
	for(auto to:edge[u])
	{
		if(to==fa)continue;
		dfs(to,u);	
	}	
}
int lca(int x,int y)
{
	if(dep[x]<dep[y])swap(x,y);
	for(int j=20;j>=0;j--)
		if(dep[f[x][j]]>=dep[y])x=f[x][j];
	if(x==y)return x;
	for(int i=20;i>=0;i--)
		if(f[x][i]!=f[y][i])
			x=f[x][i],y=f[y][i];
	return f[x][0];
}
void ST()
{
	for(int i=2;i<=n;i++)
	{
		st[i][0]=val[lca(i-1,i)];
//		cout<<"*&&&"<<lca(i,i+1)<<" "<<val[lca(i,i+1)]<<endl;
	}
	
	for(int j=1;j<=20;j++)
	{
		for(int i=1;i+(1<<j)-1<=n;i++)
		{
			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
}
int query(int l,int r)
{
	int k=log2(r-l+1);
	return max(st[l][k],st[r-(1<<k)+1][k]);
}
void kruskal()
{
	for(int i=1;i<=2*n;i++)fa[i]=i;
	now=n;
	for(int i=1;i<=m;i++)
	{
		int fu=find(G[i].u),fv=find(G[i].v);
		if(fu!=fv)
		{
			++now;val[now]=G[i].w;
			fa[fv]=now;fa[fu]=now;
			edge[now].pb({fu});
			edge[now].pb({fv});
		}
	}
	dfs(now,0);
//	for(int i=now;i;i--)
//		if(!vis[i])dfs(i,0);
//	n*=2;
	ST();
}

int main()
{
	ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);	
//	freopen("lagrange2.in","r",stdin);
	
	cin>>n>>m>>q;int u,v;G.pb({0,0});
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v;
		G.pb({u,v,i});
	}
	kruskal();
	int l,r;
	while(q--)
	{
		cin>>l>>r;
		if(l==r)cout<<0<<endl;
		else
		{
			cout<<query(l+1,r)<<endl;
		}
	}
	return 0;
}

T3

T4

标签:return,cout,int,mid,集训,fa,暑假,ans,CSP
From: https://www.cnblogs.com/wlesq/p/18325507

相关文章

  • 『模拟赛』暑假集训CSP提高模拟8
    Rank诶好像把7咕了,那就咕吧。膜拜博弈论带我上Rank1。A.基础的生成函数练习题(gf)原[ABC093C]SameIntegers先给\(a\),\(b\),\(c\)按升序排个序,求出相邻两数之差。若较小的两数之差(\(a\)和\(b\))为奇数,先操作\(\lfloor{\frac{b-a}{2}}\rfloor\)次使\(a=b-1\),再操......
  • 暑假集训CSP提高模拟8
    暑假集训CSP提高模拟8\(T1\)P155.基础的生成函数练习题(gf)\(100pts\)原题:[ABC093C]SameIntegers设通过操作\(a,b,c\)所能达到的最小整数为\(x\)。观察到对同两个数进行操作\(2\)等价于分别对这两个数各进行操作\(1\),在\(a,b,c\)达到\(x\)的过程中优先......
  • 【题解】「CSP模拟赛」雨天 rain
    雨天rain考场上打了一个动态开点线段树,但是被卡空间了......
  • VP CSP-J2019 江西
    不是很理解为什么江西CSP单列一年,题目难度吊打CSP-J2024T1P5681[CSP-J2019江西]面积签到题,但需要注意面积相等情况#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;lla,b,c;intmain(){ cin>>a>>b>>c; if(a*a>b*c){ cout<<"Alice......
  • 暑假集训CSP提高模拟7
    这个T1的\(n^{3}\)的SPJ效率还是太慢了,膜拜SPJ大神学长,还会画画A.Permutations&Primes这题感觉挺水的但是感觉有不是那么水,主要还是因为我赛时没想出正解,在打的表里找了一组好看的规律,打上了然后就过了.对偶数来说,我的规律正好是正解的特化,但是对奇数来说,我的规律就......
  • 「模拟赛」暑期集训CSP提高模拟6(7.23)
    \(140pts,Rank23\)题目列表A.花间叔祖B.合并rC.回收波特D.斗篷花间叔祖\(98pts\)题意:给定一个数组,选择一个大于等于2的模数,然后把数组中的数变成\(mod\)该模数后的数。只能操作一次,问操作后最少有几种不同的数。赛事分析:开始5分钟想到了算\(a_i\)中所有......
  • 2024暑假集训测试11
    前言比赛链接。这次好多外校的参加\(60\)多个人,反正至少没怎么挂分。确切的说赛时我只能冲T1、T2,T3可撤销或可持久化并查集都不会,赛后现学的,T4更抽象,可惜T2打假了。T3最后五分钟才开始看,没想直接打暴力了。但是T3数据太水了,加了捆绑还是水,赛后安排了重测。T1Pe......
  • 2024 暑假友谊赛-热身2
    TreeDestruction-洛谷|计算机科学教育新生态(luogu.com.cn)思路:树的直径。定理:在一棵树上,从任意节点y开始进行一次DFS,到达的距离其最远的节点z必为直径的一端。第一次dfs1(),从任意一个点,到达的最远的点必然是直径两端的其中一个。再从找到的端点开始dfs1(),......
  • 西安理工大学机器人NEXT-E战队 视觉组简介和24届新生暑假自学指引
    视觉组简介和24届新生暑假自学指引1.视觉组是什么RoboMaster机器人竞赛作为一个竞技机器人赛事,利用弹丸攻击对方机器人或对方场地道具装甲板是取得胜利的关键。为了更好的进行打击,仅依靠操作手的手动瞄准是远远不够的,因此。视觉组利用各类算法,开发出稳定的自动瞄准系统,能够极......
  • 暑假集训csp提高模拟7
    赛时rank42,T180,T213,T30,T420在T4挂死了,赛时胡了一个挺没有前途的\(O(n\log_2^3n)\)的做法,结果赛后发现假了,没有时间打T2,T3的暴力了。糖T1Permutations&PrimesPermutations&Primes赛时有一个特判\(n=3\)错了,挂了20pts结论非常显然,1放中间,2、3各放一边,剩下的随便......