题解:P16434 [APIO 2026 中国赛区] 蛋糕
棒棒糖题,场上脑子过载了没拼出 Sub4 的三分。\ 纪念一下这道让我拿了牌子的题。
Sub1
观察到
Sub2
显然有一种简单的构造:
这种做法对 Sub4 没有任何启发性,但这并不是我没场切 T2 的原因。
Sub3
下文记答案为
通过这种方法可以找到
再注意一下,对于更大的
我场上脑子过载了,直接把二分改成了这么个东西:
// int mid = (l + r) >> 1;
int mid = (int)((l + r) * 0.98);
其实道理是一样的,不管了反正就是冲过去了。
Sub4
我场上写了一坨妙妙代码获得了高贵的
如果没有想到首尾匹配,并且运气好在 Sub2 写的是构造
考虑到一次询问返回三种值,而 Sub3 中我们只用了其中两种,所以下一步优化一定是更加充分地利用返回值信息。\
注意到
具体地,设当前
废话
好几个月没写代码了,也没怎么复健就过来打 APIO 了。\
打完之后一直以为自己是铁牌,没想到卡线铜了。\
要不是我最后关头灵光一现把 Sub3 二分改成了丑陋的 0.98 我就是铁牌选手了。\
第一次坐飞机!北京好玩,一个月后再去(
Code
#include <bits/stdc++.h>
#include "cake.h"
//int compare_tastiness(std::vector<int> S1, std::vector<int> S2);
using namespace std;
vector<int> p;
int n, w, k, tid;
std::vector<int> bake_cakes(int N, int W, int K) {
n = N, w = W, k = K;
p.clear(), tid = 0;
if (N == 3000 && W == 100 && K == 100) {
tid = 1;
for (int i = 1; i <= 100; i++) p.push_back(i);
}
if (N == 3 && W == 3 && K == 1) {
tid = 2;
p.push_back(1), p.push_back(1);
}
if (N == 40 && W == 1000000000 && K == 30) {
tid = 3;
for (int i = 1; i <= W; i <<= 1) p.push_back(i);
}
if (N == 3000 && W == 2000 && K == 7) {
tid = 4;
for (int i = 1; i <= 2187; i++) p.push_back(i);
}
// cout << "!! " << tid << endl;
return p;
}
int find_tastiness(int m, int W, int K) {
if (tid == 1) {
for (int i = 0; i < 100; i++) {
int res = compare_tastiness({i}, {i + 1});
if (res == 0) return i + 1;
}
}
if (tid == 2) {
int res = compare_tastiness({0, 1}, {2});
if (res == -1) return 3;
if (res == 0) return 2;
if (res == 1) return 1;
}
if (tid == 3) {
int len = (int)p.size();
int l = 0, r = len - 1;
vector<int> pre, now;
while (l < r) {
int mid = (int)((l + r) * 0.98);
if (mid < l || mid > r) mid = l + r >> 1;
pre.clear();
for (int i = 0; i <= mid; i++) pre.push_back(i);
int res = compare_tastiness(pre, {mid + 1});
if (res == -1) l = mid + 1;
else r = mid;
}
pre.clear(), pre.push_back(l);
int ans = 0;
for (int i = l - 1; i >= 0; i--) {
now = pre, now.push_back(i);
int res = compare_tastiness(now, {l + 1});
if (res == 0) {
pre.push_back(i);
break;
}
if (res == -1) pre.push_back(i);
}
for (int i : pre) ans |= (1 << i);
return ans;
}
if (tid == 4) {
int len = 2187;
int l = 1, r = len;
while (1) {
int step = (r - l + 1) / 3, lt = l + step, rt = r - step;
int res = compare_tastiness({lt - 1, rt}, {l - 1, r});
// cout << '\t' << l << ' ' << lt << ' ' << rt << ' ' << r << ' ' << res << endl;
if (res == 0) l = lt, r = rt;
if (res == -1) r = lt - 1;
if (res == 1) l = rt + 1;
if (r - l <= 2) break;
}
if (r - l == 2) {
int res = compare_tastiness({l - 1, r}, {l, r - 1});
if (res == 1) return l;
if (res == 0) return l + 1;
if (res == -1) return r;
} else if (r - l == 1) {
int res = compare_tastiness({l - 1}, {l});
if (res == 0) return l;
else return r;
} else return l;
}
return 0;
}