AtCoder Beginner Contest 328

A - Not Too Hard

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n, x;
	cin >> n >> x;
	int res = 0;
	for (int i = 1, s; i <= n; i ++) {
		cin >> s;
		if (s <= x)
			res += s;
	}
	cout << res << "\n";
	return 0;
}

B - 11/11

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n;
	cin >> n;

	int cnt = 0;
	for(int i = 1, d, x, y; i <= n; i ++) {
		cin >> d;
		x = i % 10, y = i;
		while(y) {
			if(y % 10 == x) y /= 10;
			else x = -1, y = 0;
		}
		if(x == -1) continue;
		for( int j = x; j <= d; j = j * 10 + x)
			cnt ++;
	}
	cout << cnt << "\n";
	return 0;
}

C - Consecutive

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n, q;
	cin >> n >> q;

	string s;
	cin >> s, s = " " + s;

	vi a(n);
	for(int i = 1; i < n; i ++) 
		a[i] = (s[i] == s[i+1]) + a[i-1];

	for(int l, r; q; q --) {
		cin >> l >> r, r --;
		cout << a[r] - a[l-1] << "\n";
	}
	return 0;
}

D - Take ABC

用栈模拟一下,每次判断最后三个是不是ABC

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	string s;
	cin >> s;
	
	vector<char> stk;

	for(auto i : s) {
		stk.push_back(i);
		while(stk.size() >= 3 and stk[stk.size() - 3] == 'A' and stk[stk.size() - 2] == 'B' and stk[stk.size() - 1] == 'C')
			stk.pop_back(), stk.pop_back(), stk.pop_back();
	}
	for(auto i : stk)
		cout << i;
	return 0;
}

E - Modulo MST

因为\(n\)很小,所以我们可以用一个二进制数来表示那些点与\(1\)联通,如果一条边可以被选择,这一定是一个点与 1 联通,另一个店不联通。然后我们可以用set记录下每种状态所有选边的权重之和。剩下的就是简单的bfs。

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;

i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n, m, k;
	cin >> n >> m >> k;

	vector<array<int,3>> edge(m);
	for(auto &[u, v, w] : edge) cin >> u >> v >> w, u --, v --;

	vector<set<int>> f(1 << n);
	queue<int> q;

	f[1].insert(0),	q.push(1);
	
	vi vis(1 << n);
	while(not q.empty()) {
		int x = q.front();
		q.pop();
		if(vis[x]) continue;
		vis[x] = 1;
		for(const auto &[u, v, w] : edge){
			if(((x >> u) & 1) == ((x >> v) & 1)) continue;
			int y = x | (1 << u) | (1 << v);
			for(auto i : f[x])
				f[y].insert((i + w) % k);
			q.push(y);
		}
	}	
	cout << *f[(1 << n) - 1].begin() << "\n";
	return 0;
}	

F - Good Set Query

我们可以把一个条件当做是一条从\(a\)\(b\)的有向有权边,边权为\(d\)。同时建立一个反向边,\(-d\)。然后我们加入条件就可以转换为向生成树上建边。这样的话,我们维护出dis[i]表示从跟到\(i\)的路径长度,这样生成树两点\(x,y\)之间的距离就是\(dis[x]-dis[y]\)

对于一条边,加入有两种情况。

  1. \(a,b\)点不联通,此时说明两个之间没有任何限制条件。直接加入就好了。
  2. \(a,b\)点联通,则我们这条边加入不会影响连通性,但是我们判断这条加入是否会冲突,也就是判断\(d\)是否等于\(dis[x]-dis[y]\)

上述内容都可以使用带权并查集来维护。

#include <bits/stdc++.h>

using namespace std;


using i32 = int32_t;
using i64 = long long;

#define int i64

using vi = vector<int>;

struct dsu {
	vi fa, dis;

	dsu(int n = 1) : fa(n + 1, -1) , dis(n + 1) {};

	int getfa(int x) {
		if(fa[x] == -1) return x;
		int f = fa[x];
		fa[x] = getfa(fa[x]),dis[x] = dis[f] + dis[x];
		return fa[x];
	}

	bool merge(int x, int y, int w) {
		int fx = getfa(x), fy = getfa(y);
		if(fx != fy){
			fa[fx] = fy;
			dis[fx] = - dis[x] + dis[y] + w;
			return true;
		}else{
			return dis[x] - dis[y] == + w;
		}
	}
};


i32 main() {
	ios::sync_with_stdio(false), cin.tie(nullptr);
	int n, q;
	cin >> n >> q;
	dsu d(n);
	for(int i = 1,x , y, w; i <= q ; i ++) {
		cin >> x >> y >> w;
		if(d.merge(x, y, w)) cout << i << " ";
	}
	cout << "\n";
	return 0;
}	
posted @ 2024-05-30 22:08  PHarr  阅读(4)  评论(0编辑  收藏  举报