首页 > 其他分享 >Atcoder Beginner Contest 315 解题报告

Atcoder Beginner Contest 315 解题报告

时间:2023-08-20 11:00:13浏览次数:57  
标签:Atcoder ch Beginner Contest int void ++ -- Theta

Atcoder Beginner Contest 315

Contest link

Hints

D 尝试优化暴力。

A - tcdr

没啥好说的,模拟。

代码实现

void Solve()
{
	while(char ch=getchar())
	{
		if(!isalpha(ch))return;
		if(ch!='a'&&ch!='e'&&ch!='i'&&ch!='o'&&ch!='u')putchar(ch);
	}
}

B - The Middle Day

没啥好说的,统计总天数,找到中间的一天,再枚举月即可。

代码实现

const int N=105;
int n,a[N];
void Solve()
{
	cin>>n;
	int sum=0;
	for(int i=1;i<=n;i++)cin>>a[i],sum+=a[i];
	sum=sum+1>>1;
	for(int i=1;i<=n;i++)
		if(sum>a[i])sum-=a[i];
		else return cout<<i<<" "<<sum,void();
}

C - Flavors

只有两种情况:

  • 选择美味值最高的和第二高的;
  • 选择美味值最高的,还有与美味值最高的口味不同的中的美味值最高的。

代码实现

const int N=300005;
int n;
struct ice
{
	int f,s;
	bool operator<(const ice B)const{return s>B.s;}
}a[N];
void Solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].f>>a[i].s;
	sort(a+1,a+n+1);
	int x=0,y=0;
	if(a[1].f==a[2].f)x=a[2].s;
	for(int i=2;i<=n;i++)
		if(a[1].f!=a[i].f){y=a[i].s;break;}
	cout<<a[1].s+max(x>>1,y);
}

D - Magical Cookies

吐槽比 E 毒瘤。

有一个暴力的想法:每次检查每一行每一列,如果全一样且大于一个就标记上,然后全部删掉。

这样做,最坏情况是每次删除了一行/一列,但是却扫过了整个矩阵,时间复杂度 \(\Theta(nm(n+m))\),成功 TLE。

我们发现,这个做法的瓶颈在于检查哪一行/列可以被删除。

怎样优化?

我们可以记录每一行/列所有 \(26\) 个字母的出现次数以及剩下的字母个数。这样做,我们就可以在 \(\Theta((n+m)|\Sigma|)\) 的时间找出哪一行/列可以被删除。

进一步的,我们可以直接记录每一行/列出现过的字母个数,做到 \(\Theta(n+m)\) 的 check。

然后每次用 vector 记录要删除的点,删除的时候即可更新一下行列信息即可。注意避免重复删点。

最坏情况下,要删除 \(nm\) 个点,删点的复杂度 \(\Theta(1)\);要 check \(n+m\) 次,每次 check 是 \(\Theta(n+m)\) 的。总复杂度 \(\Theta((n+m)^2)\)。

代码实现

const int N=2005;
int n,m;
string g[N];
int cntr[N][26],cntc[N][26],typr[N],typc[N],remr[N],remc[N];
void add(int x,int y)
{
	int t=g[x][y]-'a';
	if(!cntr[x][t]++)typr[x]++;
	if(!cntc[y][t]++)typc[y]++;
	remr[x]++,remc[y]++;
}
void del(int x,int y)
{
	if(g[x][y]==' ')return;
	int t=g[x][y]-'a';
	g[x][y]=' ';
	if(!--cntr[x][t])typr[x]--;
	if(!--cntc[y][t])typc[y]--;
	remr[x]--,remc[y]--;
}
vector<PII>mk;
void Solve()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)cin>>g[i],g[i]="$"+g[i];
	for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)add(i,j);
	while(1)
	{
		bool ok=0;
		for(int i=1;i<=n;i++)
			if(typr[i]==1&&remr[i]>1)
			{
				ok=1;
				for(int j=1;j<=m;j++)mk.PB(i,j);
			}
		for(int i=1;i<=m;i++)
			if(typc[i]==1&&remc[i]>1)
			{
				ok=1;
				for(int j=1;j<=n;j++)mk.PB(j,i);
			}
		if(!ok)break;
		for(PII i:mk)del(i.first,i.second);
		mk.clear();
	}
	int ans=0;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)ans+=(bool)isalpha(g[i][j]);
	cout<<ans;
}

E - Prerequisites

水题。

把依赖关系看成一张图,则它是个 DAG。

直接从 \(1\) 开始 dfs,在 dfs 树上后序遍历即可。

代码实现

const int N=200005;
int n;
VI g[N];
bool vis[N];
void dfs(int x)
{
	if(vis[x])return;
	vis[x]=1;
	for(int y:g[x])dfs(y);
	cout<<x<<" ";
}
void Solve()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		int sz;cin>>sz;
		while(sz--){int x;cin>>x;g[i].PB(x);}
	}
	for(int i:g[1])dfs(i);
}

标签:Atcoder,ch,Beginner,Contest,int,void,++,--,Theta
From: https://www.cnblogs.com/No-play-Yes-splay/p/Atcoder-beginner-contest-315-sol.html

相关文章

  • AtCoder Beginner Contest 315
    A模拟,代码。B模拟,代码。C我们发现美味度最高的食物必选,排序后枚举即可。代码。D模拟。代码。EDFS。代码。F我们发现\(2^C\)增长很快,因此不选的数量最多只有\(\log\)次,直接DP即可。代码。G我们枚举\(i\),那么也就是求出\(Bj+Ck=X-Ai(1\lej\leN,1\lek\l......
  • AtCoder 题目集1
    AtCoder题目集1这是一个AT个人刷题总结的开始,感觉确实应该做一做这种总结,如果只是不断的刷题,感觉貌似也没有什么意思,还不如时常适当的回望一下过去的好题。希望能一直做下去吧。update(22.12.14):AT赛后总结归为另外一栏,此处为过去AT题目的记录。总结了一些比较有趣或者有思......
  • AtCoder Beginner Contest 288 - C Don't be cycle 删除图中最少的边使得图中无环
    C-Don'tbecycle题意给定一个n个顶点,m条边的无向图,你需要删除图中的一些边使得图中不存在环问你需要删除的最少边数?思路考虑连通块的生成树一个由n个顶点组成的连通块最多只能有n-1条边,不然就会成环。那么对于本题,我们只需要找到每个连通块的顶点数,那么每个连......
  • The 2022 ICPC Asia Regionals Online Contest (II) EJFB
    The2022ICPCAsiaRegionalsOnlineContest(II)EAnInterestingSequence232323232323323232323232#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;voidsolve(){ lln,k; cin>>n>>k; llres=k; llt=0; for(......
  • Atcoder_[abc284E]Count Simple Paths题解
    题目链接这题就是很简单的图上深搜,我觉得放在E题太水了,代码里有详细注释。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvector<int>v[200010];//邻接表intans;//答案boolvis[200010];//vis[i]记录i号点有没有被访问过voiddfs(intx)......
  • AtCoder Beginner Contest 311 - D(思维题)
    目录D-GridIceFloorABC简单题D思维题D-GridIceFloor题意给定一个\(n\timesm\)的矩阵,矩阵每个位置上的字符要么是'.'要么是'#',保证矩阵的最外围一圈都是'#'。玩家初始位于位置(2,2)。玩家可以进行移动,但是移动有条件:玩家首先选定一个移动方向,之后在这个方......
  • The 13th Northeast Collegiate Programming Contest
    ProblemB.BalancedDiet其实就是对每种糖果从大到小的排序后,计算前缀和后再\(O(n)\)处理,由于最多只有\(n\)个糖果,所以最大复杂度是\(O(nlogn)\)。对于题目给的每种糖果的限制\(limit\),就把当前小于\(limit\)的贡献加到\(max(limit,i)\)上。vector<int>g[N];voids......
  • The 2022 ICPC Asia Regionals Online Contest (I) C L A
    The2022ICPCAsiaRegionalsOnlineContest(I)C统计度的大小,算贡献,特判\(n=1\)#include<bits/stdc++.h>usingnamespacestd;constintN=1e6+10;typedeflonglongll;intn,d[N];vector<int>e[N];llres=0;voiddfs(intu,intfrom){ ......
  • AtCoder-ABC-267 C - Index × A(Continuous ver
    C-Index×A(Continuousver.)题目大意:给定n个数(\(a_1,a_2...a_n\)),从中选连续m个数,这m个数的和为:\(\sum_{i=1}^mi*b_i\)求最大的和为多少。\(1<=m<=n<=2*10^5\)\(-2*10^5<=a_i<=2*10^5\)解题思路首先m个数为一组,那么最多有n-m+1组,这个数量是可以被遍历的,但是......
  • AtCoder-ABC-309 C - Medicine
    C-Medicine题目大意:给n种药,第i种药吃\(a_i\)天,每天\(b_i\)粒。问最早在第几天,当天要吃的药≤K。\(1<=n<=3*10^5\)\(0<=k<=10^9\)\(1<=a_i,b_i<=10^9\)解题思路首先了解了n种药,每次都是从第一天开始,持续\(a_i\)天,所以我当时直接想到用差分来做,数组初始全为......