A. Circuit
题意:有\(n\)个灯和\(2n\)个开关,每个开关控制一个灯,每个灯被两个开关控制,如果控制一个灯的两个开关中恰好有一个打开,这个灯就会亮。你不知道具体哪些开关控制哪些灯。现在给你\(2n\)个灯的开关状态,求最少亮多少灯和最多亮多少灯。
最少的状态就是尽量让两个打开的开关控制一个灯,设有\(cnt\)个开关打开了,那么最小数就是\(cnt \% 2\)。
如果\(cnt <= n\),那么可以让每个打开的开关控制不同的灯,答案是\(cnt\),否则尽量让最少的灯被两个开关控制,答案是\(n - (cnt - n)\)。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(2 * n);for (int i = 0; i < 2 * n; ++ i) {std::cin >> a[i];}int cnt = std::count(a.begin(), a.end(), 1);std::cout << cnt % 2 << " ";if (cnt <= n) {std::cout << cnt << "\n";} else {std::cout << (n - (cnt - n)) << "\n";}
}
B. Medians
题意:给你一个序列\(a = \{1, 2, ..., n - 1, n\}\),你要把序列分成\(m\)块,其中\(m\)是奇数。并且每一块的长度都是奇数。最后结果等于每一块的中位数组成的新序列的中位数,你要使得这个数为\(k\)。
特判\(n==1\)的情况。
然后如果\(k == 1 || k == n\),则无解。因为\(k\)一定出现在最两侧。
否则看\((k - 1)\) 和 \((n - k)\)是不是奇偶性相同。如果不同的话,左边的块数一定不会等于右边的块数,\(k\)也不可能是中位数。
否则分奇偶讨论即可,保证左右两边块数相同,\(k\)单独占一块。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}int ans = n;std::sort(a.begin(), a.end());for (int i = 0, l = 0, r = 0; i + 1 < n; ++ i) {while (r < n && a[r] < a[i] + a[i + 1]) {++ r;}while (a[l] + a[l + 1] <= a[r - 1]) {++ l;}ans = std::min(ans, l + (n - r));}std::cout << ans << "\n";
}
C. Trinity
题意:给你一个数组,你每次可以让其中一个数变成另一个数。你要使得任意三个数都可以组成三角形。求最小操作数。
排序后枚举最小的两个数,因为答案最小,那么这两个数一定是相邻的,双指针维护即可。
点击查看代码
void solve() {int n;std::cin >> n;std::vector<int> a(n);for (int i = 0; i < n; ++ i) {std::cin >> a[i];}int ans = n;std::sort(a.begin(), a.end());for (int i = 0, l = 0, r = 0; i + 1 < n; ++ i) {while (r < n && a[r] < a[i] + a[i + 1]) {++ r;}while (a[l] + a[l + 1] <= a[r - 1]) {++ l;}ans = std::min(ans, l + (n - r));}std::cout << ans << "\n";
}
D. Genokraken
题意:交互题。有一棵树,除了\(0\)号点外其他点都最多有两条边相连。其中\(1\)号点必有儿子,并且如果\(u, v(u < v)\), 则\(fa_u < fa_v\)。你每次询问两个节点得到它们的路径是否经过了\(0\),最多询问\(2n - 6\)次。求出这棵树。
主要利用编号大的节点的父亲更大的性质,从大到小找,每次找\(i\)的父亲,\(i-1\)的父亲一定比\(i\)的编号小,于是可以从\(f_i - 1\)开始找,这样每个点最多被询问一次,总共\(n - 2\)次询问。
点击查看代码
int ask(int a, int b) {std::cout << "? " << a << " " << b << std::endl;int res;std::cin >> res;return res;
}void solve() {int n;std::cin >> n;std::vector<int> ans(n);for (int i = n - 1, j = n - 2; i ; -- i) {while (j > 0 && ask(i, j)) {-- j;}if (j > 0) {ans[i] = j;-- j;}}std::cout << "!";for (int i = 1; i < n; ++ i) {std::cout << " " << ans[i];}std::cout << std::endl;
}
E. Balanced
待补