AtCoder Beginner Contest 049

A - UOIAUAI

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	char c;
	cin >> c;
	if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') cout << "vowel";
	else cout << "consonant";
	return 0;
}

B - Thin

观察样例发现规律后直接模拟。

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int H, W;
	cin >> H >> W;
	vector<char> v(W);
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			cin >> v[j];
			cout << v[j];
		}
		cout << "\n";
		for (int j = 0; j < W; j++) cout << v[j];
		cout << "\n";
	}
	return 0;
}

C - Daydream

考虑到 \(\rm erase(r)\) 如果出现在 \(\rm dreamer\) 后面,即形如 \(\rm dreamerase\) 时,若从前往后若先分析 \(\rm dreamer\) 可能会判断错误,不如从后往前分析
将备选的字符串设置为数组,遍历。但凡与其中某个字符串匹配就用 \(\rm string\)\(\rm pop\_back\) 弹出该字符串,然后再从头开始遍历字符串数组。如果最后原本的字符串被删除为 \(0\),则说明匹配成功。
若匹配标志为 \(\rm false\),说明匹配失败。

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	string s;
	cin >> s;
	vector<string> v({"erase", "eraser", "dream", "dreamer"});
	while (1) {
		bool match = false;
		for (auto i : v) {
			int len = i.size();
			if (s.size() >= len && i == s.substr(s.size() - len, len)) {
				match = true;
				while (len--) s.pop_back();
				break;//匹配成功一个串,break掉,下一轮重新开始遍历字符串数组。
			}			
		}
		if (!match) {//匹配失败
			cout << "NO";
			return 0;
		}	
		if (s.empty()) {//如果字符串最后为空,则说明所有字符均已匹配成功
			cout << "YES";
			return 0;
		}
	}
	return 0;
}

D - Connectivity

道路涉及连通性的问题,即同一道路相互连接的各条道路之间都可相互通行,因此可以使用两个并查集,一个记录道路,一个记录铁路。

不管是道路还是铁路,对于每个城市来说一定与其连通的肯定是它在该并查集的祖先,(城市在该并查集中有祖先即说明该城市在并查集中)

一开始想数组 \(f[i][j]\) 表示与 \(i\)\(j\) 分别连通的城市个数,那么对于城市 \(u\),答案即为 \(\rm f[find(u,p_1)][find(u,p_2)]\)。初始化过程就是遍历每一个城市,\(\rm f[find(i,p_1)][find(i,p_2)]\)++。

发现空间复杂度为 \(O(n^2)\) ,舍弃。

image

观察到,对于每个点,我们只会把这个数组的一个位置+1,所以至多用到 \(N\) 个位置。可以开 \(\rm map\)<\(\rm pair\)<\(\rm int,int\)>\(\rm,int\)>,将 \((x,y)\) 当成坐标映射,即可实现空间复杂度 \(O(n)\)

#include <bits/stdc++.h>

using namespace std;
using i64 = long long;

int p1[200005], p2[200005];

int find(int x, int* p) {
	if (x != p[x]) return p[x] = find(p[x], p);
	return p[x];
} 

void merge(int x, int y, int* p) {
	p[find(x, p)] = find(y, p);	
}

int main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int N, K, L;
	cin >> N >> K >> L;
	for (int i = 1; i <= N; i++) {
		p1[i] = i;
		p2[i] = i;
	}
	
	for (int i = 1; i <= K; i++) {
		int a, b;
		cin >> a >> b;
		merge(a, b, p1);
	}
	for (int i = 1; i <= L; i++) {
		int c, d;
		cin >> c >> d;
		merge(c, d, p2);
	}
	
	map<pair<int, int>, int> ans;
	for (int i = 1; i <= N; i++) {
		ans[{find(i, p1), find(i, p2)}]++;
	}
	for (int i = 1; i <= N; i++) cout << ans[{find(i, p1), find(i, p2)}] << " ";
	return 0;
}

\(\rm plus:\) 可以使用 \(\rm AtCoder\) 自己的并查集板子:

#include<bits/stdc++.h>
#include<atcoder/dsu>

using namespace std;
using namespace atcoder; 

int main() {
    int N, K, L; 
    cin >> N >> K >> L;
    dsu uf1(N), uf2(N);
    for (int i = 0; i < K; i++) {
        int p, q; 
        cin >> p >> q; 
        p--, q--; 
        uf1.merge(p,q);
    }
    for (int i = 0; i < L; i++) {
    	int l, r; 
    	cin >> l >> r; 
    	l--, r--; 
    	uf2.merge(l,r);
    }
    map<pair<int, int>, int> m;
    for (int i = 0; i < N; i++) m[{uf1.leader(i),uf2.leader(i)}]++;
    for (int i = 0; i < N; i++) cout << m[{uf1.leader(i),uf2.leader(i)}] << " ";
    return 0;
}
posted @ 2024-08-24 17:58  胖柚の工作室  阅读(26)  评论(0)    收藏  举报