第一次做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的优化,很难想,以后实力够了再说吧