AtCoder Beginner Contest 378

1|0A - Pairing


#include <bits/stdc++.h> using namespace std; int main(){ map<int,int> cnt; for(int i = 1, x; i <= 4; i ++) { cin >> x; cnt[x] ++; } int res = 0; for(auto [x, y] : cnt) { res += y / 2; } cout << res; return 0; }

2|0B - Garbage Collection


二分

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = std::vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int N; cin >> N; vector<int> q(N + 1) , r(N + 1); for(int i = 1; i <= N; i ++) cin >> q[i] >> r[i]; int Q; cin >> Q; for(int t, d; Q; Q--) { cin >> t >> d; int L = 0, R = d, res = -1; while(L <= R){ int mid = (L + R) / 2; if(mid * q[t] + r[t] >= d) res = mid, R = mid - 1; else L = mid + 1; } cout << res * q[t] + r[t] << "\n"; } return 0; }

3|0C - Repeating


记录一下每个值最后一次出现的位置。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = std::vector<int>; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int N; cin >> N; map<int,int> lst; vi A(N + 1), B(N + 1); for(int i = 1; i <= N; i ++) { cin >> A[i]; if(lst[A[i]] == 0) B[i] = -1; else B[i] = lst[A[i]]; lst[A[i]] = i; } for(int i = 1; i <= N; i ++) cout << B[i] << " "; return 0; }

4|0D - Count Simple Paths


数据范围很小,直接记忆化搜索

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = std::vector<int>; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int H, W, K; cin >> H >> W >> K; vector<string> S(H); for(int i = 0; i < H; i ++) cin >> S[i]; int res = 0; vector<vi> vis; auto dfs = [&](auto self, int x, int y, int t) -> void { if(t == 0) { res ++; return; } for(int i = 0, fx , fy; i < 4; i ++) { fx = x + dx[i], fy = y + dy[i]; if(fx < 0 or fy < 0 or fx >= H or fy >= W) continue; if(vis[fx][fy] == 1) continue; if(S[fx][fy] == '#') continue; vis[fx][fy] = 1; self(self, fx, fy, t - 1); vis[fx][fy] = 0; } return ; }; for(int i = 0; i < H; i ++) for(int j = 0; j < W; j ++) { if(S[i][j] == '#') continue; vis = vector(H, vi(W)); vis[i][j] = 1; dfs(dfs, i, j, K); } cout << res << "\n"; return 0; }

5|0E - Mod Sigma Problem


首先我们看内部的区间和取模,我们是可以用前缀和实现的。

我们记前缀和为pre[i]

我们枚举左端点l,然后可以得到(ilpre[i])pre[l+1]×(Nl+1)。但是考虑到前缀和是取模后的结果,因此可能会出pre[i]<pre[l1]的情况,这种情况在模意义下pre[i]+mpre[l1]。因此我们要统计出比pre[l1]小的个数,我们可以用树状数组实现。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = std::vector<int>; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; struct BinaryIndexedTree{ #define lowbit(x) ( x & -x ) int n; vector<int> b; BinaryIndexedTree(int n) : n(n) , b(n+1 , 0){}; void modify( int i , int y ){ for( ; i <= n ; i += lowbit(i) ) b[i] += y; return; } int calc( int i ){ int sum = 0; for( ; i ; i -= lowbit(i) ) sum += b[i]; return sum; } }; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int N, M; cin >> N >> M; vi A(N + 1); for(int i = 1; i <= N; i ++) cin >> A[i], A[i] %= M; for(int i = 1; i <= N; i ++) A[i] = (A[i] + A[i - 1]) % M; BinaryIndexedTree bit(M); for(int i = 0 ; i <= N; i ++) bit.modify(A[i] + 1, 1); int sum = 0; for(int i = 1; i <= N; i ++) sum += A[i]; int res = 0; for(int i = 1; i <= N; i ++){ bit.modify(A[i - 1] + 1, -1); sum -= A[i - 1]; res += sum + bit.calc(A[i - 1]) * M - (N - i + 1) * A[i - 1]; } cout << res << "\n"; return 0; }

6|0F - Add One Edge 2


如果在x,y之间加一条边,则加边前一定满足,x,y的度数为2,且x,y路径上除x,y外的点度数都是3

考虑建新图,我们如果一条边的两个端点度数都是3,则这样的边出现在新图中。考虑新图会是若干的联通快,如果两个点x,y加边后符合要求,则x,y一定是插在同一个联通块上。

因此我们统计一下每个联通块可以插多少个度为2的点即可。

#include <bits/stdc++.h> using namespace std; using i32 = int32_t; using i64 = long long; #define int i64 using vi = vector<int>; using pii = pair<int,int>; const vi dx = {0, 0, 1, -1}, dy = {1, -1, 0, 0}; class dsu{ private: vector<int> fa; public: dsu( int n = 1 ){ fa = vector<int>( n+1 , -1 ) , fa[0] = 0; } int getfa( int x ){ if( fa[x] < 0 ) return x; return fa[x] = getfa( fa[x] ); } void merge( int x , int y ){ x = getfa(x) , y = getfa(y); if( x == y ) return ; if( fa[x] > fa[y] ) swap( x , y ); fa[x] += fa[y] , fa[y] = x; } bool same( int x , int y ){ x = getfa(x) , y = getfa(y); return ( x == y ); } }; i32 main(){ ios::sync_with_stdio(false), cin.tie(nullptr); int N; cin >> N; vi degree(N + 1); vector<pii> edge(N - 1); for(auto &[x, y]: edge) { cin >> x >> y; degree[x] ++, degree[y] ++; } dsu d(N); vi val(N + 1); for(const auto &[x, y]: edge) { if(degree[x] == 3 and degree[y] == 3) { d.merge(x, y); } else if(degree[x] == 3 and degree[y] == 2) { val[x] ++; } else if(degree[x] == 2 and degree[y] == 3) { val[y] ++; } } map<int,int> cnt; for(int i = 1; i <= N; i ++) { if(degree[i] == 3){ cnt[d.getfa(i)] += val[i]; } } int res = 0; for(auto [fa, num]: cnt) { res += num * (num - 1) / 2; } cout << res; return 0; }

__EOF__

本文作者PHarr
本文链接https://www.cnblogs.com/PHarr/p/18523559.html
关于博主:前OIer,SMUer
版权声明CC BY-NC 4.0
声援博主:如果这篇文章对您有帮助,不妨给我点个赞
posted @   PHarr  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2021-11-03 AtCoder Beginner Contest 169
点击右上角即可分享
微信分享提示