题解:P16434 [APIO 2026 中国赛区] 蛋糕
场上会了 56 后没有继续思考了,有点遗憾。
sub1:我写的插入 1 到 100,每次相邻比较即可。
sub2 我写的插入
sub3 就是简单二进制一下就行。
sub4 首先你发现
考虑放入
我们考虑将区间均分成三份
- 当
d 在左侧时(d \le m_1 ):m_1 和m_2 都在右侧,值偏小(不加 1)。总和是m_1 + m_2 = x - 1 。 - 当
d 在中间时(m_1 < d \le m_2 ):m_1 在左侧(加 1),m_2 在右侧(不加)。总和是m_1 + 1 + m_2 = x 。 - 当
d 在右侧时(d > m_2 ):m_1 和m_2 都在左侧,值偏大(都加 1)。总和是m_1 + 1 + m_2 + 1 = x + 1 。
那么刚刚好通过三个符号可以确定三种位置关系,且区间减小至三分之一,非常对,现在就是要处理下每次的
#include <bits/stdc++.h>
#include "cake.h"
#define rep(i, a, b) for(int i = (a); i <= (b); i ++ )
#define repf(i, a, b) for(int i = (a); i >= (b); i -- )
typedef long long ll;
using namespace std;
const int N = 1e5 + 10;
int c;
const int Mx = 1 << 29;
std::vector<int> bake_cakes(int N, int W, int K)
{
if(K == 100)
{
c = 1; vector<int> v;
rep(i, 1, 100) v.push_back(i);
return v;
}
else if(N == 3)
{
c = 2; return {2, 2, 2};
}
else if(N == 40)
{
c = 3; vector<int> v; v.push_back(1);
int x = 1;
while(x <= Mx)
{
v.push_back(x); x <<= 1;
}
return v;
}
else
{
c = 4; vector<int> v;
rep(i, 1, 2026) v.push_back(i);
return v;
}
}
int qmi(int x, int y)
{
int res = 1;
while(y)
{
if(y & 1) res = res * x;
x = x * x; y >>= 1;
}
return res;
}
int find_tastiness(int m, int W, int K)
{
if(c == 1)
{
rep(i, 1, 100)
{
if(compare_tastiness({i}, {i - 1}) == 0) return i;
}
}
else if(c == 2)
{
int op = compare_tastiness({1, 2}, {0, 3});
if(op == 0) return 2;
else if(op == 1) return 1;
else return 3;
}
else if(c == 3)
{
int k = 0; int res = 0;
repf(i, 30, 1)
{
vector<int> v;
rep(j, 0, i - 1) v.push_back(j);
if(compare_tastiness(v, {i}) == 0) { k = i + 1; break; }
}
vector<int> y; y.push_back(k - 1);
repf(i, k - 2, 1)
{
y.push_back(i); int op = compare_tastiness(y, {k});
if(op == 0) break;
else if(op == 1) y.erase(-- y.end());
else continue;
}
for(int x : y) res += qmi(2, x - 1);
return res;
}
else
{
int l = 1, r = 2000;
while(l < r)
{
int len = r - l + 1;
if(len == 2)
{
if(compare_tastiness({l}, {l - 1}) == 0) return l;
else return l + 1;
}
int S1 = len / 3 + (len % 3 > 0 ? 1 : 0);
int S2 = len / 3 + (len % 3 > 1 ? 1 : 0);
int m1 = l + S1 - 1;
int m2 = m1 + S2;
vector<int> s2;
if(m1 + m2 + 1 <= 2026) s2.push_back(m1 + m2 + 1);
else s2.push_back(2026), s2.push_back(m1 + m2 - 2026);
int op = compare_tastiness({m1, m2}, s2);
if(op == -1) r = m1;
else if(op == 0) { l = m1 + 1; r = m2; }
else l = m2 + 1;
} return l;
}
}