## A. Setting up Camp#

There are 3 types of people who need to stay in tents, with $a$, $b$, and $c$ individuals respectively. The first type, Xiaoboqi, only wants to stay alone, the second type, Xida, must stay with 2 other people, and the third type is indifferent. Each tent can accommodate a maximum of 3 people. What is the minimum number of tents needed?

Xiaoboqi stays alone, Xida forms teams internally as much as possible, and the third type fills in the gaps left by Xida, then take the ceiling of the result divided by 3.

## B. Fireworks#

There are two types of fireworks that explode at times $0,a,2a,3a,\dots$ and $0,b,2b,3b,\dots$, with each explosion lasting $m+1$ time units, meaning they explode at $[0,m],[a,a+m],[2a,2a+m],[3a,3a+m],\dots$ and $[0,m],[b,b+m],[2b,2b+m],[3b,3b+m],\dots$ respectively. For all time points, find the maximum number of fireworks that explode simultaneously.

Clearly, we can just check how many are exploding at time $m$; the answer is $(1 + \lfloor \frac{m}{a} \rfloor) + (1 + \lfloor \frac{m}{b}\rfloor)$.

## C. Left and Right Houses#

There is a street with $n$ households, divided into left and right sides by a road. Each household has a preference to live on the left or right side represented by $a_1, a_2, \dots, a_n$. Now, you need to arrange the position of the road such that at least half of the households on both sides are satisfied, while minimizing the distance from the midpoint and the road's coordinate.

Although there are many conditions, you only need to enumerate where to place the road from left to right, keeping track of the prefix sums to quickly check for validity.

## D. Seraphim the Owl#

There is a queue of length $n$, and you are currently standing at the far right of the queue (position $n+1$). Assuming you are currently at position $i$, you can jump left to position $j < i$, costing $a_j + \sum_{k=j+1}^{i} b_k$. Your goal is to jump to a position less than or equal to $m$ with the minimum cost.

The original problem is equivalent to choosing a cost $a_i$ or $b_i$ for each position, as each position will only choose one to calculate once, and the last cost is $a_i$, allowing for a valid jump plan. Note that you need to enumerate the last landing point within $[1,m]$, as there may be cases where $b$ is very small and $a$ is very large.

## E. Binary Search#

You are given a shuffled permutation of length $n$, and you can swap any two positions at most 2 times to ensure that binary search can find the answer for this permutation.

At first glance, it seems you need to construct a sequence of length $\lfloor \log_2n \rfloor$ to make binary search work correctly, but that's a misconception. It can be observed that although the binary search process is chaotic, it effectively narrows down the target interval to a unique one. We only need to let it run freely and place the answer in a randomly chosen target position.

During the binary search process, we mark which positions have been visited, allowing the remaining positions to be swapped freely, and finally find a position that hasn't been touched to swap. Note that during the random binary search, if the answer is found midway, an additional operation is needed to move the answer elsewhere.

That's roughly the idea; I just wrote it down randomly, added some `assert`

, but it works.

## F. Kirill and Mushrooms#

You are given $n$ mushrooms, each with a weight $a_1,a_2,a_3,\dots,a_n$. You can select $k$ mushrooms, and the weight is the minimum weight of the selected mushrooms multiplied by $k$. There is also a restriction: there is a permutation $p_1, p_2, p_3, \dots, p_n$, and if you choose the $k$ mushrooms, the weights of mushrooms $a_{p_1}, a_{p_2}, \dots, a_{p_{k-1}}$ are cleared and cannot be chosen. Find the minimum number of selections under the maximum weight condition.

Enumerate how many mushrooms are selected from $1$ to $n$ (though it can only be roughly half), maintaining the top $k$ remaining mushrooms and clearing the corresponding mushrooms.

It seems like you could directly use a heap, but I didn't want to think too much and just used a binary indexed tree to maintain the $k$ largest.

## G. Cook and Porridge#

There are $n$ people lined up for a meal, and there are a set of rules for sorting them in the queue. Determine if everyone can eat once within the first $D$ time units, or report that it's not possible.

I haven't written it; it seems like I need to maintain some data structure to handle it, but I don't want to write all the details.

## H. GCD is Greater#

You are given an array of size $n$, and you need to divide it into two parts, with each part containing at least 2 elements. The first part requires calculating their $\gcd$, while the second part requires calculating their $\operatorname{bitwise AND}$ plus a parameter $x$. Determine if there exists a partition scheme such that the weight of the first part is strictly greater than that of the second part.

Clearly, the $\gcd$ of the first part only needs 2 numbers because the more numbers there are, the smaller the $\gcd$ becomes; similarly, the $\operatorname{bitwise AND}$ also becomes smaller with more numbers, but it meets the target.

So I can directly enumerate the $\gcd$ and then figure out how to judge it, but I haven't written it down or thought it through; it should be doable.

## Code#

### A. Setting up Camp#

```
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 300000 + 5;
int n, a[maxn];
int main() {
#ifdef DEBUG
freopen("../assets/in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
int cnt = a;
cnt += b / 3;
b %= 3;
if (b > 0 && b + c < 3) {
puts("-1");
continue;
} else {
if (b > 0) {
c -= 3 - b;
cnt++;
}
cnt += (c + 2) / 3;
printf("%d\n", cnt);
}
}
return 0;
}
```

### B. Fireworks#

```
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 300000 + 5;
int main() {
#ifdef DEBUG
freopen("../assets/in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
long long a, b, m;
scanf("%lld%lld%lld", &a, &b, &m);
long long ans = 2 + m / a + m / b;
printf("%lld\n", ans);
}
return 0;
}
```

### C. Left and Right Houses#

```
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 300000 + 5;
int n, pre[maxn], suf[maxn];
char buf[maxn];
int main() {
#ifdef DEBUG
freopen("../assets/in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%s", &n, buf + 1);
pre[0] = 0; suf[n + 1] = 0;
for (int i = 1; i <= n; i++) {
pre[i] = pre[i - 1] + (buf[i] == '0');
}
for (int i = n; i >= 1; i--) {
suf[i] = suf[i + 1] + (buf[i] == '1');
}
pre[n + 1] = pre[n]; suf[0] = suf[1];
auto check = [&](int p) {
int l = pre[p];
int r = suf[p + 1];
return l >= (p + 1) / 2 && r >= (n - p + 1) / 2;
};
int ans = -1;
for (int i = 0; i <= n; i++) {
if (check(i)) {
if (ans == -1 || abs(n - ans - ans) > abs(n - i - i)) {
ans = i;
}
}
}
assert(ans != -1);
printf("%d\n", ans);
}
return 0;
}
```

### D. Seraphim the Owl#

```
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 300000 + 5;
int n, m, a[maxn], b[maxn];
int main() {
#ifdef DEBUG
freopen("../assets/in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
for (int i = 1; i <= n; i++) {
scanf("%d", b + i);
}
long long ans = 0, mn = a[m], sum = 0;
for (int i = n; i > m; i--) {
ans += min(a[i], b[i]);
}
for (int i = m; i >= 1; i--) {
mn = min(mn, a[i] + sum);
sum += b[i];
}
printf("%lld\n", ans + mn);
}
return 0;
}
```

### E. Binary Search#

```
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 300000 + 5;
int n, x, a[maxn];
void check() {
// for (int i = 1; i <= n; i++) {
// printf("%d%c", a[i], " \n"[i == n]);
// }
int l = 1, r = n + 1;
while (r - l > 1) {
int m = (l + r) / 2;
if (a[m] <= x) {
l = m;
} else {
r = m;
}
}
// printf(": %d %d\n", l, a[l]);
assert(r - l == 1 && a[l] == x);
}
int main() {
#ifdef DEBUG
freopen("../assets/in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &x);
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
}
vector<pair<int,int>> ans;
int l = 1, r = n + 1;
vector<int> visited(n + 1, 0);
while (r - l > 1) {
int m = (l + r) / 2;
if (a[m] == x && r - l > 1) {
int found = -1;
for (int i = 1; found == -1 && i <= n; i++) {
if (!visited[i]) found = i;
}
assert(found != -1);
ans.push_back({ m, found });
swap(a[m], a[found]);
}
visited[m] = 1;
if (a[m] <= x) {
l = m;
} else {
r = m;
}
}
if (a[l] != x) {
int found = -1;
for (int i = 1; found == -1 && i <= n; i++) {
if (a[i] == x) found = i;
}
assert(found != -1 && !visited[found]);
visited[found] = 1;
ans.push_back({ found, l });
swap(a[found], a[l]);
}
printf("%d\n", (int) ans.size());
for (auto& p: ans) {
printf("%d %d\n", p.first, p.second);
}
check();
}
return 0;
}
```

### F. Kirill and Mushrooms#

```
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <utility>
#include <set>
#include <map>
#include <vector>
using namespace std;
const int inf = 1e9 + 7;
const int maxn = 300000 + 5;
struct BIT {
static const int R = 1 << 21;
int a[R];
inline int lowbit(int x) { return x & -x; }
void insert(int i, int v) {
for (; i < R; i += lowbit(i)) a[i] += v;
}
void clear(int i) {
for (; i < R; i += lowbit(i)) a[i] = 0;
}
int findx(int p, int rk) {
// if (p > R) return -1;
if (p & 1) {
// if (p + (a[p] < rk) > R) return -1;
return p + (a[p] < rk);
} else {
if (rk > a[p]) return findx(p + lowbit(p) / 2, rk - a[p]);
else return findx(p - lowbit(p) / 2, rk);
}
}
int findx(int rk) {
return findx(R >> 1, rk);
}
} f;
int n, a[maxn], p[maxn];
int main() {
#ifdef DEBUG
freopen("../assets/in.txt", "r", stdin);
#endif
int T;
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
vector<int> lsh;
auto gid = [&](int x) -> int {
return int(lsh.end() - lower_bound(lsh.begin(), lsh.end(), x));
};
for (int i = 1; i <= n; i++) {
scanf("%d", a + i);
lsh.push_back(a[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", p + i);
}
sort(lsh.begin(), lsh.end());
lsh.resize(unique(lsh.begin(), lsh.end()) - lsh.begin());
for (int i = 1; i <= n; i++) {
f.insert(gid(a[i]), 1);
}
long long ans = 0;
int cnt = 0;
for (int i = 1; i + i - 1 <= n; i++) {
int id = f.findx(i);
int val = lsh[lsh.size() - id];
// printf("Find: %d %d\n", id, val);
if (1ll * val * i > ans) {
ans = 1ll * val * i;
cnt = i;
}
// Delete
f.insert(gid(a[p[i]]), -1);
}
printf("%lld %d\n", ans, cnt);
for (int i = 1; i <= n; i++) f.clear(gid(a[i]));
}
return 0;
}
```