A.

倒着模拟。

B.

观察 2 操作会改变奇偶性,全部排序。如果 2 操作不会改变奇偶性,分开排序。

C.

每个数不能被加两次,很容易的想到二进制(因为 0/1)。
然后先找到最大的 $2^k \leq n$,再由高到低逐位构造即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
vector<int> ans{1};
while (ans.back() * 2 <= x) {
ans.emplace_back(ans.back() * 2);
}
x -= ans.back();
for (int i = 30; i >= 0; i--) {
if (x >> i & 1) {
ans.emplace_back(ans.back() + (1LL << i));
}
}
reverse(all(ans));
cout << sz(ans) << "\n";
for (int x : ans) {
cout << x << " ";
}

D.

不难观察出来,对一个数进行操作其实是对一整个三角形进行翻转。

如果对 $(i,j)$ 进行翻转的话,那么对 $x$ 行的影响其实是 $[j+i-x,j-i+x]$ 翻转。

观察到 $j + i$ 和 $j - i$ 最多只有 $O(n)$ 种取值,所以直接打上标记,整体处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
unordered_map<int, int> mp1, mp2;
vector<int> b(n);
int row = 0, ans = 0;
while (row < n) {
rep (j, 0, n) b[j] = 0;
for (auto [x, c] : mp1) {
b[max(0, x - row)] ^= c;
}
for (auto [x, c] : mp2) {
if (x + row < n)
b[x + row] ^= c;
}
for (int j = 0; j < n; j++) {
if (j) {
b[j] ^= b[j - 1];
}
a[row][j] ^= b[j];
}
for (int j = 0; j < n; j++) {
if (a[row][j] == 1) {
ans += 1;
int y0 = j + row;
int y1 = j - row;
mp1[y0] ^= 1;
mp2[y1 + 1] ^= 1;
}
}
row++;
}
cout << ans << "\n";

E.

对于任意一组 (a, b),答案为最长1前缀+(a<b)+1(忽略二进制下为0的位)

可以用字典树维护(当然也可以直接分治)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

long long ans = 0;
auto dfs = [&](auto &dfs, int p) {
if (p == 0) {
return;
}
int lc = ch[p][0];
int rc = ch[p][1];
ans += sz[lc] * sz[rc] % P;
if (ans >= P) {
ans -= P;
}
dfs(dfs, lc);
ans += sz[rc] * sz[rc] % P;
if (ans >= P) {
ans -= P;
}
dfs(dfs, rc);
};

dfs(dfs, 1);

ans += 1ll * n * n % P;
if (ans >= P) {
ans -= P;
}

F.

对于值域 $[l, r]$,最多的次数显然是 $[l,r]$ 值域内的数字个数,考虑相邻的相同数字 $v$ 的位置 $pos1, pos2$,当 $(pos1,pos2)$ 内小于 $v$ 的最大值小于 $l$ 的时候可以少做一次操作(因为可以把对这俩数的操作直接连起来)

扫描线即可。

submission

G.

咕咕。

H.