AtCoder Beginner Contest 411

A.Required Length

思路:直接判断字符串大小

和题目给定长度的关系即可。

做法:见代码

int main(){
	string s;
	int n;
	cin >> s >> n;
	if(s.size() >= n) cout << "Yes";
	else cout << "No";
 	return 0;
}

B.Distance Table

循环求出任意两点间的距离即可。

int d[N], ans[N][N];

int main(){
	int n;
	cin >> n;
	for(int i = 1; i < n; i++) cin >> d[i];
	for(int i = 1; i <= n; i++){
		int sum = 0;
		for(int j = i; j < n; j++){
			sum += d[j];
			ans[i][j+1] = sum;
		}
	}
	for(int i = 1; i <= n; i++){
		for(int j = i + 1; j <= n; j++) cout << ans[i][j] << ' ';
		cout << endl;
	}

 	return 0;
}

C.Black Intervals

思路:思考什么样的操作才会使得答案改变

int main(){
	int n, q;
	cin >> n >> q;
	int res = 0;
	while(q--){
		int x;
		cin >> x;
		if(a[x] == 0){// 0 -> 1
			if(a[x-1] == 0 && a[x+1] == 0) res++;
			if(a[x-1] == 1 && a[x+1] == 1) res--;
		}else{// 1 -> 0
			if(a[x-1] == 1 && a[x+1] == 1) res++;
			if(a[x-1] == 0 && a[x+1] == 0) res--;
		}
		a[x] = 1 - a[x];
		cout << res << endl;
	}

 	return 0;
}

D - Conflict 2

问题描述

有一个服务器和 N 台电脑(PC)。服务器和每台 PC 各维护一个字符串,初始时所有字符串都是空的。

接下来给出 Q 个查询。每个查询的形式是以下三种之一:

1 p:将第 p 台 PC 的字符串替换为服务器的当前字符串。
2 p s:将字符串 s 追加到第 p 台 PC 的字符串末尾。
3 p:将服务器的字符串替换为第 p 台 PC 的当前字符串。

请在按顺序处理完所有的查询后,输出服务器最终的字符串。

注意到字符串一定是连续的,是从开始到后面某一段,所以直接链表维护即可。

#include <bits/stdc++.h>
using namespace std;

struct Node {
    int seg;
    int prev;
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int N, Q;
    cin >> N >> Q;

    vector<string> segs; 
    segs.reserve(Q);
    vector<Node> nodes;
    nodes.reserve(Q);

    vector<int> head_pc(N+1, -1);
    int head_server = -1;

    for(int qi = 0; qi < Q; qi++){
        int opt, p;
        cin >> opt >> p;
        if(opt == 1){
            head_pc[p] = head_server;
        }
        else if(opt == 2){
            string s;
            cin >> s;
            segs.push_back(s);
            int seg_idx = (int)segs.size() - 1;
            int prev_idx = head_pc[p];
            int new_node_idx = (int)nodes.size();
            nodes.push_back({seg_idx, prev_idx});
            head_pc[p] = new_node_idx;
        }
        else if(opt == 3){
            head_server = head_pc[p];
        }
    }

    vector<int> parts;
    parts.reserve(nodes.size());
    int cur = head_server;
    while(cur != -1){
        parts.push_back(nodes[cur].seg);
        cur = nodes[cur].prev;
    }
    reverse(parts.begin(), parts.end());

    size_t total_len = 0;
    for(int idx: parts){
        total_len += segs[idx].size();
    }
    string ans;
    ans.reserve(total_len);
    for(int idx: parts){
        ans += segs[idx];
    }

    cout << ans;
    return 0;
}

E.E[max]

我们有 N 个六面骰子。骰子从 1 到 N 编号,骰子 i 的六个面上写的数字分别是:

Ai,1, Ai,2, ..., Ai,6。

现在,所有 N 个骰子将被同时掷出。请计算:每个骰子朝上的面上的数字中最大值 的期望值,结果对 998244353 取模 。

对于任意一个骰子来说,它在被掷出时,哪个面朝上是独立且等概率 地选择的。

你需要计算的是这个最大值的期望,并将其对 998244353 取模输出。


显然我们色子按面分开,枚举最大值计算期望,每次就是比最大值大的每个面都不投到的概率,注意叠加关系即可。


F

直接用并查集维护,启发式合并,把度数少的合并到度数多的,启发式合并,因为复杂度瓶颈在与合并,这样就是log的了,然后既然已经log了,你就可以用set或者maplog的来删边,因为对于每个相邻点,O(n)去删一条边显然是不可接受的。


#include <iostream>
#include <vector>
#include <numeric>
#include <set>
#include <algorithm>
using namespace std;
int find_set(int v, std::vector<int>& parent) {
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v], parent);
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    int N, M;
    std::cin >> N >> M;

    std::vector<std::pair<int, int>> initial_edges(M + 1);
    std::vector<std::set<int>> adj(N + 1);
    
    for (int i = 1; i <= M; ++i) {
        int u, v;
        std::cin >> u >> v;
        initial_edges[i] = {u, v};
        adj[u].insert(v);
        adj[v].insert(u);
    }

    vector<int> parent(N + 1);
    iota(parent.begin(), parent.end(), 0);

    long long edgecnt = M;

    int Q;
    cin >> Q;

    for (int q = 0; q < Q; ++q) {
        int x;
        cin >> x;

        int u = initial_edges[x].first;
        int v = initial_edges[x].second;

        int root_u = find_set(u, parent);
        int root_v = find_set(v, parent);
        
        if (root_u != root_v && adj[root_u].count(root_v)) {
            if (adj[root_u].size() < adj[root_v].size()) {
                swap(root_u, root_v);
            }

            edgecnt--;
            adj[root_u].erase(root_v);
            adj[root_v].erase(root_u);

            for (int neighbor : adj[root_v]) {
                adj[neighbor].erase(root_v);

                if (adj[root_u].count(neighbor)) {
                    edgecnt--;
                } else {
                    adj[root_u].insert(neighbor);
                    adj[neighbor].insert(root_u);
                }
            }

            parent[root_v] = root_u;
            adj[root_v].clear();
        }

        cout << edgecnt << "\n";
    }

    return 0;
}

G

无向有重边图简单环计数

posted @ 2025-06-22 15:19  Dreamers_Seve  阅读(25)  评论(0)    收藏  举报