首页 > 其他分享 >ABC338 A~D讲题

ABC338 A~D讲题

时间:2024-02-02 18:33:59浏览次数:32  
标签:ABC338 const int text 讲题 long MAXN 配料

A

\(\text{Link}\)

给你一个长度为 \(n\) 的字符串 \(s\),判断 \(s\) 是否满足以下条件:

  • \(s\) 的第一个字符是大写字母,其余字符都是小写字母。

代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1e5 + 5;

char s[105];

int main() {
	scanf("%s", s + 1);
	int len = strlen(s + 1);
	if(s[1] < 'A' || s[1] > 'Z') {
		printf("No\n");
		return 0;
	}
	for (int i = 2; i <= len; i++) {
		if(s[i] < 'a' || s[i] > 'z') {
			printf("No\n");
			return 0;
		}
	}
	printf("Yes\n");
	return 0;
}

B

\(\text{Link}\)

给你一个由小写英文字母组成的字符串 \(s\)。请找出在 \(s\) 中出现频率最高的字符。如果存在多个这样的字符,请输出按字典序最早的那个。

思路:

用 \(tong_i\) 表示字母表中第 \(i\) 个字母出现的次数。

注意,字符串里的每个字符其实是他们的 \(\text{ASCII}\) 码值而非第几个字母。

然后遍历一遍 \(26\) 个字母,找出出现最多的中出现最早的输出即可。

代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 1e5 + 5;

char s[1005];
int tong[105];

int main() {
	scanf("%s", s + 1);
	int len = strlen(s + 1);
	for (int i = 1; i <= len; i++) {
		tong[s[i] - 'a' + 1] ++;
	}
	int maxn = -1;
	int maxx;
	for (int i = 1; i <= 26; i++) {
		if(tong[i] > maxn) {
			maxn = tong[i];
			maxx = i;
		}
	}
	printf("%c", char(maxx + 'a' - 1));
	return 0;
}

C

\(\text{Link}\)

冰箱里有 \(n\) 种配料,\(1, 2,\dots,N\)。配料 \(i\) 有 \(Q_i\) 克。

有 \(2\) 种菜。制作一份 A 菜,需要 \(A_i\) 克的配料 \(i\)。制作一份 B 菜,需要 \(B_i\) 克配料 \(i\)。每种菜只能做整数份。

最多可以制作多少份菜?

思路:

注意到 \(A_i, B_i, Q_i \le 10^6\),也就是说每种菜最多能做 \(10^6\) 份。枚举 A 菜的数量 \(i\),从 \(1\sim 10^6\),算出做 \(i\) 份 A 菜,每种配料需要多少,然后看看用剩下的配料最多能做多少份 B 菜,与答案取 \(\max\)。

代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

const int MAXN = 1e5 + 5;

int n;
int q[15], a[15], b[15];
int qq[15];
int ans;

signed main() {
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &q[i]);
	}
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &a[i]);
	}
	for (int i = 1; i <= n; i++) {
		scanf("%lld", &b[i]);
	}
	for (int i = 0; i <= 1000000; i++) {
		bool f = true;
		for (int j = 1; j <= n; j++) {
			qq[j] = q[j];
			if(i * a[j] > qq[j]) {
				f = false;
				break;
			}
			else {
				qq[j] -= i * a[j];
			}
		}
		if(!f) continue;
		int nowans = LONG_LONG_MAX;
		for (int j = 1; j <= n; j++) {
			if(b[j]) {
				nowans = min(nowans, qq[j] / b[j]);
			}
		}
		ans = max(ans, nowans + i);
	}
	printf("%lld\n", ans);
	return 0;
}

D

\(\text{Link}\)

推销下我的题解,点个赞呗QwQ

给定一张 \(n\) 个点的无向图,第 \(i\) 个点和第 \(i \bmod n + 1\) 个点之间有一条边。

现在要断掉一条边,然后按照给定顺序遍历全部点,求最小代价。

思路:

设 \(v_i\) 为断掉第 \(i\) 座桥之后所花费的代价。

考虑从 \(a\) 城市到 \(b\) 城市的代价。有两种情况:

  1. 走 \(a,a+1,a+2,\cdots,b\),代价为 \(b-a\);

  2. 走 \(a,a-1,a-2,\cdots,b\),代价为 \(n+a-b\)。

如果断掉的桥在 \(1\) 号路线上,我们只能走 \(2\) 号路线;反之只能走 \(1\) 号路线。我们显然可以通过 \(m-1\) 次暴力操作求出 \(v_i\),总复杂度 \(\Theta (nm)\),但是数据范围太大,不可行。

考虑优化。我们不难发现,我们每次对一段的区间的加法操作总是一段连续区间(因为 \(1\) 和 \(n\) 之间也有一条边),而且加的数还是定值,显然可以差分。直接套差分板子,最后求一遍前缀和,答案即为 \(\min_{i=1}^{n}v_i\)。

代码:

#include <bits/stdc++.h>
using namespace std;

const int MAXN = 2e5 + 5;

int n, m;
int x[MAXN];
long long v[MAXN];
long long ans = LONG_LONG_MAX;

int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= m ;i++) {
		scanf("%d", &x[i]);
	}
	auto dist = [&] (int from, int to) {
		if(from <= to) return to - from;
		else return n + to - from;
	};
	auto add = [&] (int from, int to, int num) {
		if(from <= to) {
			v[from + 1] += num;
			v[to + 1] -= num;
		}
		else {
			v[from + 1] += num;
			v[n + 1] -= num;
			v[1] += num;
			v[to + 1] -= num;
		}
	};
	for (int i = 1; i < m; i++) {
		add(x[i], x[i + 1], dist(x[i + 1], x[i]));
		add(x[i + 1], x[i], dist(x[i], x[i + 1]));
	}
	for (int i = 1; i <= n; i++) {
		v[i] += v[i - 1];
		ans = min(ans, v[i]);
	}
	printf("%lld", ans);
	return 0;
}

标签:ABC338,const,int,text,讲题,long,MAXN,配料
From: https://www.cnblogs.com/ljlbj-fengyuwuzu/p/18003654

相关文章

  • abc338解题报告
    A略B略C略D简要题意思路点拨考虑对于相邻的两个需要旅行的元素\((u,v)\),我们认为\(u<v\)。如果一个桥的左端点在\(u\)到\(v-1\)之间,需要\(n-v+u\)的代价。反之只需要\(v-u\)的代价。使用差分数组维护即可。E简要题意思路点拨对于一条边\(u,v\)认为\(......
  • ABC338 F
    link观察到\(n\)的范围不大,考虑状压。\(dp_{i,S}\)表示在经过顶点集合状态为\(S\)的情况下,终点为\(i\)的最小步数。错误示范:考虑对于状态\(S\),直接遍历经过的顶点\(i\),枚举\(i\)的出边进行转移。#include<bits/stdc++.h>typedeflonglongLL;typedefstd::......
  • 题解 [ABC338D] Island Tour
    【洛谷博客】被降智的一道简单题。题意\(n\)个岛屿,第\(i\)座桥连接\(i\)和\(i+1\)(第\(N\)座桥连接着\(1\)和\(N\))。有一条长度为\(M\)的旅游序列\(X\),你需要按照顺序依次经过这些点,选择断掉一座桥使得旅游经过的桥最少。分析设断掉第\(i\)座桥会因为绕行增......
  • ABC338D 题解
    赛时怎么连这题都不会。再不练练思维真的就连普及题都不会做了啊。Solution题目来源:ABC338D(inAtcoder|in洛谷)。不妨先考虑应该断掉哪条边。首先我们发现,仅断掉一条边并不会让两个结点不可达,只会让我们从一个结点绕更远的路到达目标结点。如果我们要从结点\(u\)前往结点......
  • ABC338 F Negative Traveling Salesman 题解
    QuestionABC338FNegativeTravelingSalesman给出一个\(N\)个点\(M\)条边的有向图,边权可能为负数,但不可能有负环每经过一条边就要加上这条边的代价求,一条路径经过所有的点,并且要求总代价最小Solution观察到\(N\le20\)自然而然想到状压因为多次经过一条边的代价是......
  • ABC338 D Island Tour 题解
    Question有\(n\)座海岛由\(n\)条桥连着,第\(i\)座桥连接第\(i\)和\(i+1\)座海岛,第\(n\)座桥连接第\(n\)和\(1\)座海盗有一条长度为\(m\)的旅游路线,第\(X_i\)表示依次到达的岛屿现在需要切断一条桥,求总旅游路线最小值Solution显然,从第\(X_{i-1}\)到\(X_......
  • ABC338 E Chords 题解
    Question一个圆上有\(2N\)个点均匀分布,给出\(N\)条线,每条线连接两个顶点问,有没有两条线相交Solution也算一个比较典的题目考虑到这种两两配对,配对中有没有交错关系的可以考虑异或哈希因为一个数异或两次等于它本身,所以我们可以用异或来实现一个“撤销”操作我们当我......
  • ABC338 题解(A-E)
    前言:F,G后续补充。A题意判断一个字符串,是否满足只有第一位为大写字母,其余为小写字母。Sol字面意思模拟即可。Code#include<bits/stdc++.h>#definelllonglong#defineN200005#defineendl"\n"#definefifirst#definesesecondusingnamespacestd;constll......
  • 20230712 讲题
    CF1364DEhab'sLastCorollary简单题。特判掉\(m=n-1\)的情况,此时一定能找到一个大小为\(\left\lceil\frac{k}{2}\right\rceil\)的独立集,二分图染色即可。否则,我们建出dfstree,找到一条连接的两个端点深度之差最小的返祖边,设它为\((u,v)\),且\(dep_u>dep_v\)。......
  • 20230703 讲题
    CF1394DBoboniuandJianghu容易发现若\(b_u\neb_v\)则边的方向确定,问题转化为给\(b_u=b_v\)的边定向。设\(f_{u,0/1}\)为\(u\)连向父亲的点的方向是\(u\tofa\)还是\(fa\tou\)。我们知道一个点的贡献系数是\(\max(in,out)\),其中\(in\)和\(out\)为入......