VP AtCoder Beginner Contest 378


A - Pairing

点击查看代码
void solve() {
	std::map<int, int> mp;
	for (int i = 0; i < 4; ++ i) {
		int x;
		std::cin >> x;
		++ mp[x];
	}
    int ans = 0;
    for (auto & [x, y] : mp) {
    	ans += y / 2;
    }

    std::cout << ans << "\n";
}

B - Garbage Collection

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n), b(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i] >> b[i];
    }

    int q;
    std::cin >> q;
    while (q -- ) {
    	int t, d;
    	std::cin >> t >> d;
    	-- t;
    	int x = d % a[t];
    	if (x == 0) {
    		x = a[t];
    	}
    	int ans = x <= b[t] ? b[t] - x + d : a[t] - x + b[t] + d;
    	std::cout << ans << "\n";
    }
}

C - Repeating

题意:找ai前面最靠近i的等于ai的位置。

map存每个数上次出的位置,从前往后遍历。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<int> b(n + 1, -1);
    std::map<int, int> last;
    for (int i = 1; i <= n; ++ i) {
    	if (last.count(a[i])) {
    		b[i] = last[a[i]];
    	}

    	last[a[i]] = i;
    }

    for (int i = 1; i <= n; ++ i) {
    	std::cout << b[i] << " \n"[i == n];
    }
}

D - Count Simple Paths

题意:求矩阵里所有长度为k的路径。

数据都很小,直接爆搜。

点击查看代码
void solve() {
    int n, m, k;
    std::cin >> n >> m >> k;
    std::vector<std::string> s(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> s[i];
    }

    const int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};

    int ans = 0;
    std::vector st(n, std::vector<int>(m));
    auto dfs = [&](auto self, int x, int y, int t) -> void {
    	if (t == k) {
    		++ ans;
    		return;
    	}

    	for (int i = 0; i < 4; ++ i) {
    		int nx = x + dx[i], ny = y + dy[i];
    		if (nx < 0 || nx >= n || ny < 0 || ny >= m || s[nx][ny] == '#' || st[nx][ny]) {
    			continue;
    		}

    		st[nx][ny] = 1;
    		self(self, nx, ny, t + 1);
    		st[nx][ny] = 0;
    	}
    };

    for (int i = 0; i < n; ++ i) {
    	for (int j = 0; j < m; ++ j) {
    		if (s[i][j] == '.') {
    			st[i][j] = 1;
    			dfs(dfs, i, j, 0);
    			st[i][j] = 0;
    		}
    	}
    }

    std::cout << ans << "\n";
}

E - Mod Sigma Problem

题意:给你一个数组,求所有区间的区间和对m取模后的值的和。注意最后这个和不需要取模。

求出对m取模后的前缀和sum,那么对于每个i,前面对它的贡献为j=0i1(sumisumj+m)%m。发现sumisumj0的时候加不加m都没区间,那么有多少个sumj>sumi就要加几个m。用树状数组维护维护。

点击查看代码
template <class T>
struct Fenwick {
    int n;
    std::vector<T> tr;

    Fenwick(int _n) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        tr.assign(_n + 1, T{});
    }

    void add(int x, const T &v) {
        for (int i = x; i <= n; i += i & -i) {
            tr[i] = tr[i] + v;
        }
    }

    T query(int x) {
        T res{};
        for (int i = x; i; i -= i & -i) {
            res = res + tr[i];
        }
        return res;
    }

    T sum(int l, int r) {
        return query(r) - query(l - 1);
    }
};

void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<int> sum(n + 1);
    for (int i = 0; i < n; ++ i) {
    	sum[i + 1] = (sum[i] + a[i]) % m;
    }

    Fenwick<int> tr(m + 1);
    i64 ans = 0, pre = 0;
    for (int i = 1; i <= n; ++ i) {
    	ans += (i64)i * sum[i] - pre;
    	ans += (i64)tr.sum(sum[i] + 1, m) * m;
    	if (sum[i] > 0) {
    		tr.add(sum[i], 1);
    	}
    	pre += sum[i];
    }

    std::cout << ans << "\n";
}

F - Add One Edge 2

题意:在一棵树里加一条边,使得产生的边里的每个点度数都为3。不能产生重边。

发现肯定使加在两个度数为2的点之间,并且这两个点在树上的路径的点的度数必须都是3。那么我们可以用并查集维护所有度数为3的点的联通块,然后枚举每个联通块里的每个点连接多少给度数为2的点,这些点两两可以产生贡献。

点击查看代码
struct DSU {
	std::vector<int> fa, cnt;
	DSU(int _n) {
		init(_n);
	}

	void init(int _n) {
		fa.assign(_n, 0);
		cnt.assign(_n, 1);
		std::iota(fa.begin(), fa.end(), 0);
	}

	int find(int x) {
		return x == fa[x] ? x : fa[x] = find(fa[x]);
	}

	bool merge(int x, int y) {
		x = find(x), y = find(y);
		if (x == y) {
			return false;
		}

		fa[y] = x;
		cnt[x] += cnt[y];
		return true;
	}

	bool same(int x, int y) {
		return find(x) == find(y);
	}

	int size(int x) {
		return cnt[find(x)];
	}
};

void solve() {
    int n;
    std::cin >> n;
    std::vector<std::vector<int>> adj(n);
    for (int i = 1; i < n; ++ i) {
    	int u, v;
    	std::cin >> u >> v;
    	-- u, -- v;
    	adj[u].push_back(v);
    	adj[v].push_back(u);
    }

    DSU dsu(n);
    for (int u = 0; u < n; ++ u) {
    	if (adj[u].size() == 3) {
    		for (auto & v : adj[u]) {
    			if (adj[v].size() == 3) {
    				dsu.merge(u, v);
    			}
    		}
    	}
    }	

    std::vector<std::vector<int>> S(n);
    for (int i = 0; i < n; ++ i) {
    	S[dsu.find(i)].push_back(i);
    }

    i64 ans = 0;
    for (int i = 0; i < n; ++ i) {
    	if (adj[i].size() != 3) {
    		continue;
    	}

    	int cnt = 0;
    	for (auto & u : S[i]) {
    		for (auto & v : adj[u]) {
    			if (adj[v].size() == 2) {
    				++ cnt;
    			}
    		}
    	}

    	ans += (i64)cnt * (cnt - 1) / 2;
    }

    std::cout << ans << "\n";
}
posted @   maburb  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示