AtCoder Beginner Contest 243

本文分享了作者在AtCoder编程竞赛中的体验,包括简单题目(a/b题)的解决策略,如直接模运算和使用哈希映射。接着讨论了更复杂的题目(c/d/e题),涉及碰撞检测、二叉树路径计算和弗洛伊德算法。文章指出部分题目因理解错误或复杂度挑战未能解答,并提供了部分题目的解决方案和关键点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次做atcoder, ab很简单,c题有点麻烦,d题看错了,但是看对了应该也做不出来emmm,e题floyd,补题的时候因为初始化距离太小debug了半天, f和g略微看了看(做出了abc题)

a, b题都太简单了, a题直接用v对(a + b + c)取模就行。然后看谁最先减到0;b题直接开个map存a,读取b的时候看看是否在a中出现过并且对应位置是否一直即可;

C - Collision 2

题意:读入n个点的人的坐标,输入字符串s, 表示对应的第i个人向左走还是向右走,判断是否相撞;

处理:先找到每一行的最左向右走的人和最右向左走的人(开个map来维护),遍历一次人的坐标,如果这个人的坐标处于最左向右走的人右边并且向左走或者处于最右向左的人的左边并且向右走,就会相撞,否则不会。

#include <bits/stdc++.h>
 
using namespace std;
 
const int N = 1e6 + 10;
 
struct Pos{
	int x, y;
}pos[N];
 
map<int, pair<int, int>> st;
 
int main()
{
    int n;
    cin >> n;
    //1 -> l, 2 -> r 
    for(int i = 0; i < n; i ++ ) {
    	int x, y;
    	cin >> x >> y;
    	pos[i].x = x;
     	pos[i].y = y;
	}
	string s;
	cin >> s;
	
	for(int i = 0; i < s.size(); i ++ ) {
		int x = pos[i].x, y = pos[i].y;
		if(s[i] == 'R' && (st[y].first == 0 || x < st[y].first))
			st[y].first = x;
		if(s[i] == 'L' && (st[y].second == 0 || x > st[y].second))
			st[y].second = x;
	}
	
	for(int i = 0; i < s.size(); i ++ ) {
		int x = pos[i].x, y = pos[i].y;
		if(st[y].second != 0 && s[i] == 'R' && x < st[y].second) {
			puts("Yes");
			return 0;
		}
		if(st[y].first != 0 && s[i] == 'L' && st[y].first < x) {
			puts("Yes");
			return 0;
		}
	}
	
	puts("No");
	
    return 0;
}

D - Moves on Binary Tree 

题意:一个完全二叉树的模型,初始位置在x点,给定一个长度为n的字符串,u为向父节点走,l为向左孩子走,r为向右孩子走。判断x的最终位置。

ps;当时我直接看以为不会爆long long,以为很简单,结果半天没看出哪里错了,太菜了

处理:(c++用高精度貌似会超时)模拟一个deque,一个l或者r可以抵消一个u, 放的时候模拟出一个栈,l的话就往栈放1,r放2, u就pop,题目保证结果不会爆long long,最后从头读入一遍结果就行。

#include <bits/stdc++.h>
#define int long long
 
using namespace std;
 
signed main()
{
	int n, x;
	cin >> n >> x;
	string s;
	cin >> s;
	
	vector<int> deq;
	for(int i = 0; i < s.size(); i ++ ) {
		if(s[i] == 'R') deq.push_back(1);
		else if(s[i] == 'L') deq.push_back(2);
		else {
			if(!deq.empty()) deq.pop_back();
			else {
				x /= 2;
			}
		}
	}
	for(int i : deq) {
		if(i == 1) x = x * 2 + 1;
		else x *= 2;
	}
	cout << x;
	return 0;
}

E - Edge Deletion

考点:floyd(多源汇最短路)

题意:给定一个无向连通图,问最多能删除多少遍,使得各个点之间的最短距离不发生改变。

处理:ans = 边数 - 不能删除的边(如果不能有任意一条边k,使得dist[i][j] == dist[i][k] + dist[k][j],那么这个边就是不能删除的,人话就是这条边不能由其他边所取代)

ps:初始化距离不能设成1e9(0x3f3f3f3f),设的大一点

#include <bits/stdc++.h>
#define int long long
 
using namespace std;
 
const int N = 1000, INF = 1e18;
 
int dist[N][N], n, m;
 
void floyd()
{
	for(int k = 1; k <= n; k ++ )
		for(int i = 1; i <= n; i ++ )
			for(int j = 1; j <= n; j ++ )
				dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
}
 
signed main()
{	
	cin >> n >> m;
	
	for(int i = 1; i <= n; i ++ )
		for(int j = 1; j <= n; j ++)
			if(i == j) dist[i][j] = 0;
			else dist[i][j] = INF;
	
	for(int i = 0; i < m; i ++ ) {
		int a, b, c;
		cin >> a >> b >> c;
		dist[a][b] = min(dist[a][b], c);
		dist[b][a] = min(dist[b][a], c);
	}
	
	floyd();
	
	int res = 0;
	for(int i = 1; i <= n; i ++ )
		for(int j = 1; j <= n; j ++ ){
			int fl = 1;
			if(i == j) continue;
			for(int k = 1; k <= n; k ++ )
				if(i != k && j != k && dist[i][j] == dist[i][k] + dist[k][j])
					fl = 0;
			res += fl;
		}
					
	cout << m - res / 2 << "\n";
	
	return 0;
}

F题考了一个组合数学 && 容斥定理&&dp,难度太大做不了

G题考了一个dp的优化,很难想,以后实力够了再说吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值