首页 > 其他分享 >AtCoder Beginner Contest 352

AtCoder Beginner Contest 352

时间:2024-05-05 18:45:11浏览次数:13  
标签:巨人 AtCoder Beginner int long 352 using include define

AtCoder Beginner Contest 352

A - AtCoder Line

给 \(N,X,Y,Z\) 判断是否 \(\min(X,Y)\le Z\le \max(X,Y)\)。

模拟。

点击查看代码
#include<bits/stdc++.h>
#define int long long

using namespace std;
int n,x,y,z;
signed main(){
	cin>>n>>x>>y>>z; if(x>y) swap(x,y);
	if(x<=z&&z<=y) cout<<"Yes";
	else cout<<"No";
	return 0;
}

B - Typing

给 \(S,T\),而 \(S\) 是 \(T\) 的字典序最小子序列,求 \(S\) 在 \(T\) 中的位置。

模拟。

点击查看代码
#include<bits/stdc++.h>
#define int long long

using namespace std;
char s[200003],t[200003];
signed main(){
	cin>>s>>t;
	int pos=0;
	for(int i=0;t[i];i++){
		if(t[i]==s[pos]) cout<<i+1<<' ',pos++;
	}
	return 0;
}

C - Standing On The Shoulders

有 \(N\) 个巨人,他们的名字分别是 \(1\) 到 \(N\) 。当巨人 \(i\) 站在地上时,他们的肩高是 \(A_i\) ,头高是 \(B_i\) 。

你可以选择 \((1, 2, \ldots, N)\) 的 \((P_1, P_2, \ldots, P_N)\) 排列组合,并根据以下规则堆叠 \(N\) 个巨人:

  • 首先,将 \(P_1\) 巨人放在地上。巨人 \(P_1\) 的肩膀距离地面的高度为 \(A_{P_1}\) ,头部距离地面的高度为 \(B_{P_1}\) 。
  • 为了 \(i = 1, 2, \ldots, N - 1\) 的顺序,要把巨人 \(P_{i + 1}\) 放在巨人 \(P_i\) 的肩膀上。如果巨人 \(P_i\) 的肩膀距离地面的高度是 \(t\) ,那么巨人 \(P_{i + 1}\) 的肩膀距离地面的高度就是 \(t + A_{P_{i + 1}}\) ,他们的头距离地面的高度就是 \(t + B_{P_{i + 1}}\) 。

求最上面的巨人 \(P_N\) 的头部距离地面的最大可能高度。

贪心,显然肩膀的高度是堆叠的,而头的高度只能算一个,所以把所有肩膀加上以后再找到头到肩膀高度差最大的那个就行。

点击查看代码
#include<bits/stdc++.h>
#define int long long

using namespace std;
int n,a,b,mx,ans;
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a>>b;
		ans+=a,mx=max(b-a,mx);
	}
	cout<<ans+mx;
	return 0;
}

D - Permutation Subsequence

给你一个排列 \(P\),求一个长度为 \(k\) 的子序列,使得该子序列的数字是连续的,且子序列头尾位置差最小。

类似滑动窗口,因为要求数字连续,所以我们可以用 set 维护每连续 \(k\) 个数的位置最大最小值,然后向右滑动更新答案即可。

点击查看代码
#include<bits/stdc++.h>
#define int long long

using namespace std;
int n,k;
int pos[200003],a[200003];
set<int>s;
signed main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i],pos[a[i]]=i;
	}
	for(int i=1;i<=k;i++) s.insert(pos[i]);
	auto it=s.end(); it--;
	int ans=(*it)-(*(s.begin()));
	for(int i=k+1;i<=n;i++){
		s.erase(pos[i-k]);
		s.insert(pos[i]);
		it=s.end(); it--;
		ans=min(ans,(*it)-(*(s.begin())));
	}
	cout<<ans;
	return 0;
}

E - Clique Connect

给你一个加权无向图 \(G\) ,有 \(N\) 个顶点,编号为 \(1\) 至 \(N\) 。最初, \(G\) 没有边。

您需要执行 \(M\) 次操作来为 \(G\) 添加边。 \((1 \leq i \leq M)\) 的 \(i\) -th 操作如下:

  • 给你一个由 \(K_i\) 个顶点组成的顶点子集 \(S_i=\lbrace A_{i,1},A_{i,2},\dots,A_{i,K_i}\rbrace\) 。对于每一对 \(u, v\) ,即 \(u, v \in S_i\) 和 \(u<v\) ,在顶点 \(u\) 和 \(v\) 之间添加一条边,权重为 \(C_i\) 。

完成所有 \(M\) 操作后,确定 \(G\) 是否相连。如果是,求 \(G\) 最小生成树中各条边的总重。

将问题分成两部分,一是判断连通,二是求 MST。

一很好弄,因为所给的每个每个集合之间的块是连通的,直接用并查集处理。

二的话,每个集合里的边是平方级别的,而我们只需要保证连通即可求 MST,所以每个集合里的点只需要保留 \(K_i-1\) 条边即可。最后再对图用 Kruskal 求 MST 即可,时间复杂度 \(O(\sum K\log \sum K)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long

using namespace std;
int n,m;
int fa[400003],k[400003],c[400003];
vector<int>a[400003];
void init(){for(int i=1;i<=n;i++)fa[i]=i;}
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y){fa[find(x)]=find(y);}
bool query(int x,int y){return find(x)==find(y);}
int ffa[400003];
void finit(){for(int i=1;i<=n;i++)ffa[i]=i;}
int ffind(int x){return ffa[x]==x?x:ffa[x]=ffind(ffa[x]);}
void fmerge(int x,int y){ffa[ffind(x)]=ffind(y);}
bool fquery(int x,int y){return ffind(x)==ffind(y);}
struct edge{
	int u,v,w,id;
	bool operator<(const edge &o)const{return w<o.w;}
}e[800003];int cnt;
signed main(){
	cin>>n>>m; init(); finit();
	for(int i=1;i<=m;i++){
		cin>>k[i]>>c[i];
		for(int j=1,A;j<=k[i];j++){
			cin>>A;
			a[i].push_back(A);
		}
		for(int j=1;j<k[i];j++){
			merge(a[i][j-1],a[i][j]);
			e[++cnt]={a[i][j-1],a[i][j],c[i],cnt};
			e[++cnt]={a[i][j],a[i][j-1],c[i],cnt};
		}
	}
	for(int i=2;i<=n;i++){
		if(!query(i,i-1)){
			cout<<"-1\n";
			return 0;
		}
	}
	int ans=0;
	sort(e+1,e+cnt+1);
	for(int i=1;i<=cnt;i++){
		if(!fquery(e[i].u,e[i].v)){
			fmerge(e[i].u,e[i].v);
			ans+=e[i].w;
		}
	}
	cout<<ans;
	return 0;
}

标签:巨人,AtCoder,Beginner,int,long,352,using,include,define
From: https://www.cnblogs.com/DEV3937/p/18173728/abc352

相关文章

  • AtCoder Grand Contest 001
    D.ArraysandPalindrome如果两个字符要求相同就给它们连边,对于一个长度为\(x\)的回文串,\(x\)是偶数会连\(x/2\)条边,奇数会连\(x/2-0.5\)条边。\(a\)和\(b\)两个序列总和为\(2n\),要让\(n\)个字符相同至少连\(n-1\)条边,也就是奇数个数超过\(2\)时一定无解......
  • AtCoder Beginner Contest 352题解
    AtCoderBeginnerContest352Time:2024-05-04(Sat)20:00-2024-05-04(Sat)21:40AAtCoderLine问题陈述AtCoder铁路线有$N$个车站,编号为$1,2,\ldots,N$。在这条线路上,有趟进站列车从$1$站出发,依次停靠$2,3,\ldots,N$站,有趟出站列车从$N$站出发,依次停......
  • 题解:AT_abc352_C [ABC352C] Standing On The Shoulders
    考场憋了很久,最后代码贼短……理想状态下,直接全排列解决问题。但是,\(1\len\le2\times10^5\),明显TLE,试都不用试的。咋优化呢?其实,前面的巨人只负责“打地基”,作为“塔尖儿”的巨人有且仅有1个。而前面地基随便排列,地基高度(他们的和)都不会变。所以,我们只需要枚举塔尖即......
  • ABC352
    Alink\(x\)停不到,\(y\)能停到。要先判断是从前往后还是从后往前。点击查看代码#include<bits/stdc++.h>usingnamespacestd;signedmain(){ intn,x,y,z; cin>>n>>x>>y>>z; if(x<=y){ if(z>x&&z<=y)cout<<......
  • ABC352
    A.AtCoderLine判断\(z\)是否出现在\(x\)和\(y\)之间即可代码实现n,x,y,z=map(int,input().split())ifx>y:x,y=y,xifx<z<y:print('Yes')else:print('No')B.Typing模拟代码实现#include<bits/stdc++.h......
  • AtCoder Beginner Contest 352 考试总结
    前言正常发挥。属于是\(4\)个月没搞OI,复健成功了!得分明细:ABCDEFGTotal√√√√√××1475改题明细:ABCDEFG√√√√√××第一次正式rated打AT,行吧!A.AtCoderLineProblemAtCoder铁路线有\(N\)个车站,编号为\(1......
  • AtCoder abc352
    EProblemStatementYouaregivenaweightedundirectedgraph$G$with$N$vertices,numbered$1$to$N$.Initially,$G$hasnoedges.Youwillperform$M$operationstoaddedgesto$G$.The$i$-thoperation$$(1\leqi\leqM)$$isasfollows:Youar......
  • 《自动机理论、语言和计算导论》阅读笔记:p352-P401
    《自动机理论、语言和计算导论》学习第12天,p352-P401总结,总计50页。一、技术总结1.TuringMachine(TM)2.undecidability​a.Ld(thediagonalizationlanguage)3.reductionp392,Ingeneral,ifwehaveanalgorithmtoconvertinstancesofaproblemP1toi......
  • AtCoder Beginner Contest 351
    A-Thebottomoftheninth(abc351A)题目大意给定\(9\)个\(a_i\)和\(8\)个\(b_i\),问最后一个\(b_9\)是多少,使得\(\suma_i<\sumb_i\)。解题思路答案就是\(\suma_i-\sumb_i+1\)。神奇的代码a=sum(map(int,input().split()))b=sum(map(int,input().......
  • [atcoder]【LCR114] [
    importjava.util.*;classSolution{publicstaticvoidmain(String[]args){Solutionsolution=newSolution();Stringstr=solution.alienOrder(newString[]{"wrt","wrf","er","e......