AtCoder Beginner Contest 348

A题: Penalty Kick

签到题

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n; cin >> n;
	for (int i = 1; i <= n; i ++ ) {
		if (i % 3 == 0) cout << 'x';
		else cout << 'o';
	}
	return 0;
}

 B题: Farthest Point

暴力模拟题

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n; cin >> n;
	vector<int> a(n), b(n);
	for (int i = 0; i < n; i ++ ) cin >> a[i] >> b[i];
	for (int i = 0; i < n; i ++ ) {
		int id = 0, dist = 0;
		for (int j = 0; j < n; j ++ ) {
			if (i == j) continue;
            int now = (a[j] - a[i]) * (a[j] - a[i]) + (b[j] - b[i]) * (b[j] - b[i]);
			if (now > dist) {
				id = j;
				dist = now;
			}
		}
		cout << id + 1 << endl;
	}
	return 0;
}

 C题: Colorful Beans

思路:用桶(map)存对应颜色的最小美味度,然后遍历取最大即可。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n; cin >> n;
	map<int, int> p;
	for (int i = 0; i < n; i ++ ) {
		int a, c;
		cin >> a >> c;
		if (!p[c]) p[c] = a;
		else p[c] = min(p[c], a);
	}
	int ans = 0;
	for (auto t : p) {
		ans = max(ans, t.second);
	}
	cout << ans << endl;
	return 0;
}

D题:  Medicines on Grid

显然bfs,不过vis数组要改一下,不能简单地使用bool数组,可以参考最后一个样例。

vis存的是到当前点的最大能量,这样我们bfs的时候,只有当能量大于vis的时候才丢到queue里面。

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 210;
char g[N][N];
int vis[N][N], b[N][N];
int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	memset(vis, -1, sizeof vis);
	int h, w;
	cin >> h >> w;
	pair<int, int> f;
	queue<array<int, 3>> q;
	for (int i = 1; i <= h; i ++ ) {
		for (int j = 1; j <= w; j ++ ) {
			cin >> g[i][j];
			if (g[i][j] == 'S') {
				q.push({i, j, 0});
			}
			if (g[i][j] == 'T') {
				f = {i, j};
			}
		}
	}
	int n; cin >> n;
	while (n -- ) {
		int r, c, e; cin >> r >> c >> e;
		b[r][c] = e;
	}
	while (q.size()) {
		auto t = q.front(); q.pop();
		int x = t[0], y = t[1], e = t[2];
		e = max(b[x][y], e);
		vis[x][y] = e;
		if (e <= 0) continue;
		for (int i = 0; i < 4; i ++ ) {
			int x1 = x + dx[i], y1 = y + dy[i];
			if (x1 < 1 || x1 > h || y1 < 1 || y1 > w) continue;
			if (vis[x1][y1] >= e - 1) continue;
			if (g[x1][y1] == '#') continue;
			q.push({x1, y1, e - 1});
			vis[x1][y1] = e - 1;
		}
	}
	if (vis[f.first][f.second] < 0) cout << "No\n";
	else cout << "Yes\n";
	return 0;
}

E题: Minimize Sum of Distances

换根dp

推荐up主->

【Atcoder ABC348 E讲解(换根DP)】https://www.bilibili.com/video/BV14m42177cJ?vd_source=140a9a07403bc18393f243c29b890edf

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
const int N = 1e5 + 9;
int n; ll tot;
ll a[N], dp[N], sum[N];
vector<int> e[N];
void dfs(int now, int lst, ll dep) {
	dp[1] += a[now] * dep;
	sum[now] += a[now];
	for (auto x : e[now]) {
		if (x == lst) continue;
		dfs(x, now, dep + 1);
		sum[now] += sum[x];
	}
	tot += a[now];
}
void ddfs(int now, int lst) {
	for (auto x : e[now]) {
		if (x == lst) continue;
		dp[x] = dp[now] + tot - 2 * sum[x];
		ddfs(x, now);
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin >> n;
	for (int i = 1; i < n; i ++ ) {
		int u, v; cin >> u >> v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	for (int i = 1; i <= n; i ++ ) cin >> a[i];
	dfs(1, 0, 0);
	ll ans = dp[1];
	ddfs(1, 0);
	for (int i = 2; i <= n; i ++ ) ans = min(ans, dp[i]);
	cout << ans << endl;
	return 0;
}

F题: Oddly Similar

显然暴力的方法是O(N^{2}M),这肯定是过不了的。

所以我们可以结合位运算的知识,进行解题。

我们用bs存每列中元素存在的位置,用bt存每行的信息

我们只是在找固定一列后,每行相等的元素进行操作!

从矩阵左边往右边看,一开始大家都没有相似,然后看第一列,会将与其值相等的列异或到bt里面去,接着再进行操作,如果还是之前相同的行,这样异或起来就会是0,而同值不同的行可以异或为1,这样就实现了题目的模拟。

如果列数是奇数,那么每行都存在自己跟自己的一种情况,要减去n。

然后这是相互的,所以ans / 2

#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
using ll = long long;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	int n, m; cin >> n >> m;
	vector<vector<int>> a(n, vector<int>(m));
	for (int i = 0; i < n; i ++ ) {
		for (int j = 0; j < m; j ++ ) {
			cin >> a[i][j];
		}
	}
	vector<bitset<2000>> bt(n);
    vector<bitset<2000>> bs(1000);
    for (int i = 0; i < m; i ++ ) {
    	for (int j = 0; j < n; j ++ ) {
    		bs[a[j][i]].set(j);
    	}
    	for (int j = 0; j < n; j ++ ) {
    		bt[j] ^= bs[a[j][i]];
    	}
    	for (int j = 0; j < n; j ++ ) {
    		bs[a[j][i]].reset(j);
    	}
    }
    int ans = 0;
    for (int i = 0; i < n; i ++ ) ans += bt[i].count();
    if (m & 1) ans -= n;
    cout << ans / 2 << endl;
    return 0;
}

  • 14
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值