首页 > 其他分享 >[题解](更新中)AtCoder Beginner Contest 383(ABC383) A~E

[题解](更新中)AtCoder Beginner Contest 383(ABC383) A~E

时间:2024-12-08 22:37:38浏览次数:8  
标签:AtCoder idx Beginner int 题解 long ans include define

A - Humidifier 1

照题意模拟即可,时间复杂度\(O(n)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 110
using namespace std;
int n,t[N],v[N],sum;
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>t[i]>>v[i];
	for(int i=1;i<=n;i++){
		sum=max(0ll,sum-(t[i]-t[i-1]));
		sum+=v[i];
	}
	cout<<sum<<"\n";
	return 0;
}

B - Humidifier 2

\(O((nm)^2)\)枚举两个加湿器的位置,再\(O(nm)\)统计答案。

总时间复杂度\(O((nm)^3)\)。

点击查看代码
#include<bits/stdc++.h>
#define N 15
using namespace std;
int n,m,d,ans;
string s[N];
signed main(){
	cin>>n>>m>>d;
	for(int i=1;i<=n;i++){
		cin>>s[i];
		s[i]=' '+s[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(s[i][j]=='#') continue;
			for(int k=1;k<=n;k++){
				for(int l=1;l<=m;l++){
					if(s[k][l]=='#') continue;
					int cnt=0;
					for(int o=1;o<=n;o++){
						for(int p=1;p<=m;p++){
							if(s[o][p]=='#') continue;
							cnt+=(abs(o-i)+abs(p-j)<=d||abs(o-k)+abs(p-l)<=d);
						}
					}
					ans=max(ans,cnt);
				}
			}
		}
	}
	cout<<ans<<"\n";
	return 0;
}

C - Humidifier 3

对于一个位置,我们显然要让最优的状态先遍历到它,所以使用BFS解决。

初始将所有H所在位置加入队列,然后正常进行BFS即可。

时间复杂度\(O(nm)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define N 1010
using namespace std;
struct Status{int x,y,d;};
int n,m,d,dx[4]{-1,0,1,0},dy[4]{0,1,0,-1};
bitset<N> vis[N];
queue<Status> q;
string s[N];
signed main(){
	cin>>n>>m>>d;
	for(int i=1;i<=n;i++) cin>>s[i],s[i]=' '+s[i];
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++)
		if(s[i][j]=='H') q.push({i,j,0});
	while(!q.empty()){
		Status sta=q.front();
		q.pop();
		int x=sta.x,y=sta.y;
		if(vis[x][y]) continue;
		vis[x][y]=1;
		if(sta.d==d) continue;
		for(int i=0;i<4;i++){
			int xx=x+dx[i],yy=y+dy[i];
			if(xx<1||yy<1||xx>n||yy>m||s[xx][yy]=='#') continue;
			q.push({xx,yy,sta.d+1});
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			ans+=vis[i][j];
		}
	}
	cout<<ans<<"\n";
	return 0;
}

D - 9 Divisors

因数个数公式:对于\(n=p_1^{a_1}\times p_2^{a_2}\times\dots\times p_l^{a_k}\)(\(p_i\)表示互不相同的质数),\(n\)的因数个数是\(\prod\limits_{i=1}^k (a_i+1)\)。

根据上面的公式,我们发现一个数\(x\)拥有恰好\(9\)个因数,当且仅当下面一项成立:

  • \(x=p_1^2\times p_2^2\)。
  • \(x=p_8\)。

显然成立的\(p\)一定在\(O(\sqrt n)\)以内,所以我们线性筛得到\(\sqrt n\)以内的素数,按上面的方法计算出所有答案,再统计\(\le n\)的有多少个即可。

显然答案一定远小于\(\sqrt n\)(这个看最后一个样例也能得到),所以时间复杂度不会超过\(O(\sqrt n)\)。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define V 2000010
#define CNT 500010
using namespace std;
int n,ans[CNT],idx,prime[V],idxp;
bitset<V> vis;
void euler(){
	vis[0]=vis[1]=1;
	for(int i=2;i<=V;i++){
		if(!vis[i]) prime[++idxp]=i;
		for(int j=1;j<=V;j++){
			if(i*prime[j]>V) break;
			vis[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}
}
signed main(){
	cin>>n;
	euler();
	for(int i=1;i<=idxp;i++){
		int ii=prime[i]*prime[i];
		for(int j=i+1;j<=idxp;j++){
			int jj=prime[j]*prime[j];
			if(ii>4e12/jj) break;
			ans[++idx]=ii*jj;
		}
	}
	for(int i=1;i<=idxp;i++){
		int v=prime[i];
		v=v*v*v*v*v*v*v*v;
		if(v>4e12) break;
		ans[++idx]=v;
	}
	int cnt=0;
	for(int i=1;i<=idx;i++) cnt+=(ans[i]<=n);
	cout<<cnt<<"\n";
	return 0;
}

E - Sum of Max Matching

最小化两点间边权最大值,是无向图的最小瓶颈路问题,我们通常使用最小生成树或Kruskal重构树(此处使用前者)来解决。

结论:原图上两点间最大边权的最小值,就是最小生成树上两点间的最大边权。

由此我们可以得到一个贪心思路:

  • 初始将每个节点看作一个集合。对于\(u\)所在的集合,进行如下规定:
    • 如果\(u\in A\)则该集合包含\(1\)个红色点。
    • 如果\(u\in B\)则该集合包含\(1\)个蓝色点。
    • 否则该集合为空。
  • 按边权从小到大为边集排序,依次遍历每一条边\((u,v,w)\):
    • 如果加入该边后形成环,则跳过这条边。
    • 否则,将\(u,v\)所在集合合并,红蓝点两两配对消去。设消去\(s\)个红蓝点对,那么对答案的贡献就是\(s\times w\)。

根据一开始的结论,可以得出这样做是正确的。

时间复杂度\(O(m(\log m+\alpha(n)))\)。

点击查看代码
#include<bits/stdc++.h>
#define N 200010
#define M 200010
#define int long long
using namespace std;
struct edge{int u,v,w;}e[M];
int n,m,k,ca[N],cb[N],idx,fa[N],ans;
vector<edge> G[N];
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
signed main(){
	cin>>n>>m>>k;
	for(int i=1,u,v,w;i<=m;i++){
		cin>>u>>v>>w;
		e[++idx]={u,v,w};
	}
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1,u;i<=k;i++) cin>>u,ca[u]++;
	for(int i=1,u;i<=k;i++) cin>>u,cb[u]++;
	sort(e+1,e+1+idx,[](edge a,edge b){return a.w<b.w;});
	for(int i=1;i<=m;i++){
		int u=find(e[i].u),v=find(e[i].v);
		if(u==v) continue;
		fa[u]=v,ca[v]+=ca[u],cb[v]+=cb[u];
		int siz=min(ca[v],cb[v]);
		ca[v]-=siz,cb[v]-=siz;
		ans+=siz*e[i].w;
	}
	cout<<ans<<"\n";
	return 0;
}

F - Diversity

周二更新

标签:AtCoder,idx,Beginner,int,题解,long,ans,include,define
From: https://www.cnblogs.com/Sinktank/p/18593243

相关文章

  • CF1540B Tree Array 题解
    CF1540BTreeArray题解首先题目的时间复杂度一定是一个\(O(n^3)\)状物。一定会有一个\(n\)来枚举根节点,那么一个根内要\(O(n^2)\)地解决问题。考虑整个序列的期望是困难的,转而考虑每个点对\((x,y)\)的期望。注意到\((x,y)\)具有父子关系时,它的贡献是确定为\(0/1\)......
  • 【题解】P5787 二分图 /【模板】线段树分治
    二分图最简单的方法是染色法实现,但是扩展域并查集也可以实现,有两个集合\(S,T\),具体的是相连边的两个点\(x,y\)总是在不同的两个集合中,若出现在同一集合中即不是一个二分图。对于时间段建边考虑用线段树储存,线段树按照时间轴划分,将将对应时间区间的节点储存上当前连边操作,小时......
  • P9951 [USACO20FEB] Swapity Swap B 题解
    题目传送门思路注意到\(1\leK\le10^9\),暴力显然会超时。将每次操作后的数列输出出来,发现会在一定次数的翻转后,重新回到初始数列。\(1\leN\le100\),循环节一定不会太长,所以暴力处理循环节长度即可。代码#include<bits/stdc++.h>usingnamespacestd;intn,lo,k,l1,l2,r......
  • 2024icpc上海E题题解及感想
    2024icpc上海E题题解​ 在这场icpc区域赛之前,我们队已经打了icpc南京和ccpc重庆,分别拿了银牌和铜牌。这场其实是非常希望可以拿金牌的,但是E题最后还是没能做出来,所以还是拿了一块银牌。​ 不过赛后拿到补题链接后用赛时思路写了一遍,发现赛时的思路假了。​ 但是后来转念一想,为......
  • [CF576E] Painting Edges 题解
    模版题的升级了。使用二分图经典判定方法(一个点拆成两个点\(x,x+n\),连边\((x,y)\)就是连接\((x,y+n),(x+n,y)\),那么是否是二分图就等价于判断\(x,x+n\)是否都不在一个集合内),预处理出每个操作的\(e_i\)下一次出现的位置\(nx_i\),每一次修改边相当于给\((i,nx_i)\)这个区......
  • 【Atcoder】【ABC383】A- Humidifier 1加湿器 题解
    前言不知道大家有没有关注过AtCoder这是小日子那边的一个网站,每周都会有比赛比起CF等等,最大的优点就是延迟低,题目质量也不错计划以后每周更新题解了正文题目传送门A-Humidifier1题目大意有一个加湿器,给定有次操作,第次在时间加入胜水然而,如果加湿器里有水,它每个单......
  • AT_arc188_a [ARC188A] ABC Symmetry 题解
    容易发现一个串是好的的充要条件是:A,B,C出现次数的奇偶性都相同。因此我们也可以将所有的串分为四类:好的,只有A和其他两个的奇偶性不同,只有B和其他两个的奇偶性不同,只有C和其他两个的奇偶性不同。大于\(k\)的不好统计,可以直接用总数减去小于\(k\)的总和。设$f_{i,x,......
  • 【题解】P8865 [NOIP2022] 种花
    题目传送门题目大意有一个\(n\timesm\)的花园,\(a_{i,j}=1\)表示可以种花,\(a_{i,j}=0\)表示不可以种花,请求出有多少种种花的的方案,使得形成C或F的形状,\(n,m\le10^3\)。思路分析观察C和F,发现F可以认为是C的左下角加一笔竖画,所以先求C。求形成C的方案数枚......
  • ABC383E 题解
    ABC383E题解题意给定一张包含\(n\)个节点和\(m\)条无向带权边的图,以及两个序列\(A_k,B_k\)分别表示图中的某些节点,定义\(f(A_i,B_j)\)为从\(A_i\)到\(B_j\)所有路径各自包含的边权最大值中的最小值,可以任意排列\(B\)中的元素,使得\(\sum_{i=1}^kf(A_i,B_i)\)最......
  • Daiwa Securities Co. Ltd. Programming Contest 2024(AtCoder Beginner Contest 383)-C
    题目大意一个\(H\)行和\(W\)列的网格图。\((i,j)\)表示从上到下第\(i\)行和从左到下第\(j\)列的单元格。每个单元格用字符\(S_{i,j}\)表示。如果\(S_{i,j}\)为#,则该单元格有一个障碍物;如果\(S_{i,j}\)是.则该单元格是空的;如果\(S_{i,j}\)为H,则该单元网格图......