Codeforces Round 1046 (Div. 2)


A. In the Dream

题意:比赛上半场比分为\(a:b\),下半场为\(c:d\),没有一个队伍能连续赢三次,求这个比分可不可能。

一方每赢两次另一方就要断他连胜,然后最后还可以接两次胜利然后结束,那么有\(a * 2 + 2 \leq b\)\(b * 2 + 2 \leq a\)。同理处理下半场,下半场双方得分就是\(c-a, d- b\)

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int a, b, c, d;
	std::cin >> a >> b >> c >> d;
	if (a * 2 + 2 < b || b * 2 + 2 < a || (c - a) * 2 + 2 < (d - b) || (d - b) * 2 + 2 < (c - a)) {
		std::cout << "NO\n";
	} else {
		std::cout << "YES\n";
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

B. Like the Bitset

题意:构造一个排列,如果\(s_i\)\(1\),代表所有覆盖这个位置的长度至少为\(k\)的子数组的最大值不是\(p_i\)

直接从小到大填,先把\(1\)的位置填了,然后填\(0\)的位置。如果连续的\(1\)大于等于\(k\)个无解。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n, k;
	std::cin >> n >> k;
	std::string s;
	std::cin >> s;
	int x = 1;
	std::vector<int> a(n);
	for (int i = 0, cnt = 0; i < n; ++ i) {
		if (s[i] == '1') {
			a[i] = x ++ ;
			++ cnt;
		} else {
			cnt = 0;
		}

		if (cnt >= k) {
			std::cout << "NO\n";
			return;
		}
	}

	std::cout << "YES\n";
	for (int i = 0; i < n; ++ i) {
		if (a[i] == 0) {
			a[i] = x ++ ;
		}
		std::cout << a[i] << " \n"[i == n - 1];
	}
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

C. Against the Difference

题意:一个块是好的,那么每个元素都等于块长,一个数组是好的,那么可以分成若干好块。给你一个数组,求一个最长的好子序列。

考虑\(dp\)。记\(f_i\)表示前\(i\)个能选出的最长子序列,那么不选\(i\)的话\(f_i = f_{i-1}\),否则记\(j\)\(i\)前面第\(a_i\)个和它相同数的位置,有\(f_i = \max(f_i, f_{j-1} + a_i)\)。给每个元素记录位置,然后每个\(i\)记录它在相同元素里是第几位。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::vector<int> a(n + 1);
	std::vector<std::vector<int>> pos(n + 1);
	std::vector<int> p(n + 1);
	for (int i = 1; i <= n; ++ i) {
		std::cin >> a[i];
		p[i] = pos[a[i]].size();
		pos[a[i]].push_back(i);
	}

	std::vector<int> f(n + 1);
	for (int i = 1; i <= n; ++ i) {
		f[i] = f[i - 1];
		if (p[i] + 1 >= a[i]) {
			f[i] = std::max(f[i], f[pos[a[i]][p[i] - a[i] + 1] - 1] + a[i]);
		}
	}
	std::cout << f[n] << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

D. For the Champion

题意:交互题。二维平面上开始你有一个坐标\((X, Y)\),但你不知道。有\(n\)个点,你每次可以让直接上下左右选一个方向移动\([1, 10^9]\)步,然后得到所有点和你的曼哈顿距离的最小值。\(10\)次移动求出坐标。

和一个点曼哈顿距离为\(k\)的点其实是围绕这个点的一个菱形,可以看作四条线段。可以记录每个点\(45\)度和\(135\)度的对角线,分别是\(x_i + y_i\)\(x_i - y_i\)。那么可以每次移动\(K=1e9\),先移动到右上,此时距离它最近的点的\(x_i, y_i\)都小于它,那么一定是最大的\(x_i + y_i\)这条线上,记为\(max1\)。设返回距离为\(d1\),则有\(X+Y+4K-max1 = d1\),然后再移动到右下,记此时距离为\(d2\),距离它最近的点为\(i\),那么有\(X+2K - x_i + y_i - (Y - 2K) = d2\),得\(X+Y+4K - (x_i - y_i)= d2\),那么记\(max2\)为最大的\(x_i - y_i\)
则有

\begin{cases}
X + Y + 4K + max1 = d1 \\
X - Y + 4K - max2 = d2
\end{cases}
解方程即可。

点击查看代码
#include <bits/stdc++.h>

using i64 = long long;

void solve() {
	int n;
	std::cin >> n;
	std::vector<i64> x(n), y(n);
    i64 max1 = -1e18, max2 = -1e18;
	for (int i = 0; i < n; ++ i) {
		std::cin >> x[i] >> y[i];
        max1 = std::max(max1, x[i] + y[i]);
        max2 = std::max(max2, x[i] - y[i]);
	}

	auto ask = [&](char c, i64 k) -> i64 {
        std::cout << "? " << c << " " << k << std::endl;
        i64 res;
        std::cin >> res;
        return res;
    };

    constexpr i64 K = 1e9;
    ask('R', K);
    ask('R', K);
    ask('U', K);
    i64 d1 = ask('U', K);
    ask('D', K);
    ask('D', K);
    ask('D', K);
    i64 d2 = ask('D', K);
    i64 sum1 = d1 - 4 * K + max1;
    i64 sum2 = d2 - 4 * K + max2;
    i64 X = (sum1 + sum2) / 2, Y = (sum1 - sum2) / 2;
    std::cout << "! " << X << " " << Y << std::endl;
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}

E. By the Assignment

题意:一个无向图,每个点有点权,但有些点的点权还没确定。权域为\([1, V]\)。要求任意两个点的所有路径的点权异或和都相同。求有多少方案。

如果两个点有两条以上路径,那么显然成环,且这两条路径值相同,同时环上任意两点的两条路径的值相同,可以得到每个点的权值相同,如果环长是奇数,则每个点点权必须是\(0\)
那么求边双,如果边双里有奇环,则每个点权值都相同,如果只有偶环,如果每个点都没确定有\(V\)种填法,否则权值只能是已经填了的点的值。如果边双只有一个点且没有确定也是随便填。
代码省略取模类。

点击查看代码
constexpr int P = 998244353;
using Z = MInt<P>;

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

    std::vector<std::vector<std::pair<int,int>>> adj(n);
    for (int i = 0; i < m; ++ i) {
        int u, v;
        std::cin >> u >> v;
        -- u; -- v;
        adj[u].emplace_back(v, i);
        adj[v].emplace_back(u, i);
    }

    std::vector<int> dfn(n, -1), low(n, 0), stk, bel(n, -1), bridge(m);
    stk.reserve(n);
    int dcc_cnt = 0;
    int idx = 0;
    auto tarjan = [&](auto && self, int u, int fa) -> void {
        dfn[u] = low[u] = idx ++ ;
        stk.push_back(u);
        for (auto & [v, id] : adj[u]) {
            if (dfn[v] == -1) {
                self(self, v, id);
                low[u] = std::min(low[u], low[v]);
                if (low[v] > dfn[u]) {
                    bridge[id] = 1;
                }
            } else if (id != fa) {
                low[u] = std::min(low[u], dfn[v]);
            }
        }

        if (dfn[u] == low[u]) {
            int v;
            do {
                v = stk.back();
                stk.pop_back();
                bel[v] = dcc_cnt;
            } while (v != u);
            ++ dcc_cnt;
        }
    };
    
    tarjan(tarjan, 0, -1);

    std::vector<int> c(n, -1);
    bool flag = true;
    Z ans = 1;
    for (int i = 0; i < n; ++ i) {
        if (c[i] != -1) {
            continue;
        }
        int val = -1;
        auto dfs = [&](auto && self, int u, int color, int fa) -> bool {
            c[u] = color;
            if (a[u] != -1) {
                if (val == -1) {
                    val = a[u];
                } else if (val != a[u]) {
                    flag = false;
                }
            }

            bool odd_cycle = false;
            for (auto & [v, id] : adj[u]) {
                if (id == fa || bel[v] != bel[i] || bridge[id]) {
                    continue;
                }

                if (c[v] == -1) {
                    odd_cycle |= self(self, v, color ^ 1, id);
                } else if (c[u] == c[v]) {
                    odd_cycle = true;
                }
            }

            return odd_cycle;
        };

        if (dfs(dfs, i, 0, -1)) {
            if (val != -1 && val != 0) {
                flag = false;
            } 
        } else if (val == -1) {
            ans *= V;
        }

        if (!flag) {
            std::cout << 0 << "\n";
            return;
        }
    }
    std::cout << ans << "\n";
}

int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	std::cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}
posted @ 2025-08-29 12:47  maburb  阅读(242)  评论(0)    收藏  举报