AtCoder Beginner Contest 378
A - 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;
}
B - 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;
}
C - 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;
}
D - 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;
}
E - Mod Sigma Problem
首先我们看内部的区间和取模,我们是可以用前缀和实现的。
我们记前缀和为\(pre[i]\)。
我们枚举左端点\(l\),然后可以得到\((\sum_{i \ge l} pre[i]) - pre[l + 1] \times (N - l + 1)\)。但是考虑到前缀和是取模后的结果,因此可能会出\(pre[i] < pre[l-1]\)的情况,这种情况在模意义下\(pre[i] + m - pre[l-1]\)。因此我们要统计出比\(pre[l-1]\)小的个数,我们可以用树状数组实现。
#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;
}
F - 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;
}