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;
}


posted @ 2024-11-03 16:15  PHarr  阅读(9)  评论(0编辑  收藏  举报