Codeforces Round 1056 (Div. 2) A~D

A - El fucho

模拟。

胜者组共有 \(n-1\) 队进入败者组,进入败者组的会淘汰 \(n-2\) 队,最后剩两组再进行一场,总场数 \(2n-2\)

不会算也可以直接模拟。

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

using i64 = long long;

void solve() {

	int n;
	std::cin >> n;

	int m = 0, ans = 0;
	while(n > 1) {
		ans += n / 2;
		m += n / 2;
		n -= n / 2;
	}

	while(m > 1) {
		ans += m / 2;
		m -= m / 2;
	}

	ans += 1;

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

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

	int t;
	std::cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

B - Abraham's Great Escape

构造。

只要有两个就可以构造出 \(\text{LR}\) 这样的循环,然后其他的可以在第一排放 \(\text L\) 指向它,然后再在下面的排放 \(U\) 指向它,其他走出迷宫放 \(D\) 即可。

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

using i64 = long long;

void solve() {

	int n, k;
	std::cin >> n >> k;

	if(n * n - k == 1) {
		std::cout << "NO\n";
		return;
	}

	k = n * n - k;
	std::vector<std::string> ans(n, std::string(n, 'D'));

	if(k) {
		k -= 2;
		ans[0][0] = 'R', ans[0][1] = 'L';
		for(int i = 2; i < n && k; i += 1, k -= 1) {
			ans[0][i] = 'L';
		}
		for(int i = 1; i < n && k; i += 1) {
			for(int j = 0; j < n && k; j += 1) {
				ans[i][j] = 'U';
				k -= 1;
			}
		}
	}

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

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

	int t;
	std::cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

C - The Ancient Wizards' Capes

思维。

通过手玩可以发现答案只有三种,限制太强;对于 \(|a_i-a_{i-1}|\ge 2\) 这种直接不存在,假设 \(a_i > a_{i-1}\),那么除去 \(a_i\)\(a_{i-1}\)\(a_{i-1}\) 至少也能看见 \(a_i - 2\) 个,加上它自己,只能是比 \(a_i\) 多一或者少一。

\(a_i=a_{i-1}\) 时,\(a_i\)\(a_{i-1}\) 是相反的,因为它们都能看见除掉它们两个之外的其他,它们相等,所以它们得互防;\(a_i > a_{i-1}\ \text{or}\ a_i < a_{i-1}\) 也是同理,它们之间会因为朝向而每防住另一个,此时朝向的是固定的。

所以可以枚举 \(a_1\) 作为 \(\text{LR}\),然后得出其他数的朝向,最后对每个数算一下左右两边看见和 \(a_i\) 是否相等即可,这里是用线段树进行维护。

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

using i64 = long long;

template<class Info>
struct SegmentTree {
	int n;
	std::vector<Info> info;
	SegmentTree() : n(0) {}
	SegmentTree(int n_, Info v_ = Info()) {
		init(n_, v_);
	}
	template<class T>
	SegmentTree(std::vector<T> init_) {
		init(init_);
	}
	void init(int n_, Info v_ = Info()) {
		init(std::vector(n_, v_));
	}
	template<class T>
	void init(std::vector<T> init_) {
		n = init_.size();
		info.assign(4 << std::__lg(n), Info());
		std::function<void(int, int, int)> build = [&](int p, int l, int r) {
			if (r - l == 1) {
				info[p] = init_[l];
				return;
			}
			int m = (l + r) / 2;
			build(2 * p, l, m);
			build(2 * p + 1, m, r);
			pull(p);
		};
		build(1, 0, n);
	}
	void pull(int p) {
		info[p] = info[2 * p] + info[2 * p + 1];
	}
	void modify(int p, int l, int r, int x, const Info &v) {
		if (r - l == 1) {
			info[p] = v;
			return;
		}
		int m = (l + r) / 2;
		if (x < m) {
			modify(2 * p, l, m, x, v);
		} else {
			modify(2 * p + 1, m, r, x, v);
		}
		pull(p);
	}
	void modify(int p, const Info &v) {
		modify(1, 0, n, p, v);
	}
	Info rangeQuery(int p, int l, int r, int x, int y) {
		if (l >= y || r <= x) {
			return Info();
		}
		if (l >= x && r <= y) {
			return info[p];
		}
		int m = (l + r) / 2;
		return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
	}
	Info rangeQuery(int l, int r) {
		return rangeQuery(1, 0, n, l, r);
	}
	template<class F>
	int findFirst(int p, int l, int r, int x, int y, F &&pred) {
		if (l >= y || r <= x) {
			return -1;
		}
		if (l >= x && r <= y && !pred(info[p])) {
			return -1;
		}
		if (r - l == 1) {
			return l;
		}
		int m = (l + r) / 2;
		int res = findFirst(2 * p, l, m, x, y, pred);
		if (res == -1) {
			res = findFirst(2 * p + 1, m, r, x, y, pred);
		}
		return res;
	}
	template<class F>
	int findFirst(int l, int r, F &&pred) {
		return findFirst(1, 0, n, l, r, pred);
	}
	template<class F>
	int findLast(int p, int l, int r, int x, int y, F &&pred) {
		if (l >= y || r <= x) {
			return -1;
		}
		if (l >= x && r <= y && !pred(info[p])) {
			return -1;
		}
		if (r - l == 1) {
			return l;
		}
		int m = (l + r) / 2;
		int res = findLast(2 * p + 1, m, r, x, y, pred);
		if (res == -1) {
			res = findLast(2 * p, l, m, x, y, pred);
		}
		return res;
	}
	template<class F>
	int findLast(int l, int r, F &&pred) {
		return findLast(1, 0, n, l, r, pred);
	}
};

struct Info {
	int cnt[2] {};
};

Info operator+(const Info &l, const Info &r) {
	return {l.cnt[0] + r.cnt[0], l.cnt[1] + r.cnt[1]};
}

void solve() {

	int n;
	std::cin >> n;

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

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

	SegmentTree<Info> seg(n);

	int ans = 0;
	for(int x = 0; x < 2; x += 1) {
		int lst = x;
		seg.modify(0, {1 - x, x});
		for(int i = 1; i < n; i += 1) {
			int now;
			if(a[i] == a[i - 1]) {
				now = lst ^ 1;
			} else if(a[i] > a[i - 1]) {
				now = 0;
			} else {
				now = 1;
			}
			seg.modify(i, {1 - now, now});
			lst = now;
		}

		bool ok = true;
		for(int i = 0; i < n; i += 1) {
			auto res = seg.rangeQuery(0, i + 1);
			auto res2 = seg.rangeQuery(i, n + 1);
			if(a[i] != res.cnt[0] + res2.cnt[1]) {
				ok = false;
				break;
			}
		}

		ans += ok;
	}

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

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

	int t;
	std::cin >> t;
	while (t--) {
		solve();
	}

	return 0;
}

D - Batteries

思维。

把电池按顺序摆放成一个环,每次选相邻两个数可以确定相邻两个是否存在一对好电池,同理选相隔一个的可以确定每三个是否存在一对好电池,假设两好电池间的最短距离长度为 \(l\),这样最多在第 \(l\) 轮就能找到,设好电池数量为 \(a\),则最短区间距离最大为 \(\lfloor\frac{n}{a}\rfloor\),每个数找一次,这样最多 \(n\times\lfloor\frac{n}{a}\rfloor\) 次就能找到,满足 $n\times\lfloor\frac{n}{a}\rfloor\le \lfloor\frac{n^2}{a}\rfloor $。

可能更严谨的证明(?
\(q = \lfloor\frac{n}{a}\rfloor\),则有 \(q\le \frac na< q+1\),由 \(q\le \frac na\),可得 \(nq\le \frac{n^2}a\);又因为 \(nq\) 是整数,\(\lfloor\frac{n^2}{a}\rfloor\) 是小于等于 \(\frac{n^2}a\) 的最大正整数,所以 $nq\le \lfloor\frac{n^2}{a}\rfloor \rightarrow n\times\lfloor\frac{n}{a}\rfloor\le \lfloor\frac{n^2}{a}\rfloor $。

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

using i64 = long long;

void solve() {

    int n;
    std::cin >> n;

    auto ask = [](int x, int y)->bool{
        std::cout << x << " " << y << std::endl;
        int res;
        std::cin >> res;
        return res;
    };

    for(int i = 1; i <= n; i += 1) {
        for(int j = 1; j <= n; j += 1) {
            int to = j + i;
            if(to > n){
                to -= n;
            }
            if(ask(j, to)) {
                return ;
            }
        }
    }

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

    int t;
    std::cin >> t;
    while (t--) {
        solve();
    }

    return 0;
}
posted @ 2025-10-10 15:20  Ke_scholar  阅读(103)  评论(0)    收藏  举报