2022-2023 Winter Petrozavodsk Camp, Day 2: GP of ainta

https://codeforces.com/gym/104427/attachments/download/20525/230201-tutorial.pdf

A. Reversing

只有周围同色的,才可能是被改过的,答案就是 $2^C$,C 是和周围颜色相同的点的个数。

B. Lawyers

如果一个边不存在反向边,直接选即可,然后可以顺手选了剩下白给的点。

接下来就只有若干个全是双向边的连通块,然后看这个连通块里面的点数 $c$ 和 边数 $e$ 是否满足 $c \times 2 \leq e$。

C. One, Two, Three

$O(N^2)$ 做法,考虑前 $i$ 个 1 肯定是 $(1,2,3)$,后面的都是 $(3,2,1)$,所以可以枚举 $i$。

$O(N)$ 做法:霍尔定理。

https://codeforces.com/gym/104427/attachments/download/20525/230201-tutorial.pdf

D. Lonely King

E. Treasure Box

修改位置使得回文的最小代价。


赛时做法:

一个人最多向左走一次然后一直向右走,而向左走是不会进行修改的。

所以向左走的那一次可以最后再处理。

选定一个位置开始向右走,走到的位置具有决策单调性,可以直接指针移动然后决策单调性分治。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <algorithm>
#include <bits/stdc++.h>
#include <cstdio>
#ifndef LOCAL
#define debug(...)
#else
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#endif
#define rep1(a) for (int i = 0; i < a; i++)
#define rep2(i, a) for (int i = 0; i < a; i++)
#define rep3(i, a, b) for (int i = a; i < b; i++)
#define rep4(i, a, b, c) for (int i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)

#define pb emplace_back
using namespace std;
template <typename T, typename T2> void cmin(T &x, const T2 &y) {
x = x < y ? x : y;
}
template <typename T, typename T2> void cmax(T &x, const T2 &y) {
x = x > y ? x : y;
}
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
template <class T> using vc = vector<T>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
mt19937 rng(time(NULL));
const int inf = 1000000000;
const ll lnf = 1000000000000000000;
#define sz(x) int((x).size())
#define all(x) begin(x), end(x)

template <class... T> void read() {}
template <class T> void read(T &x) { cin >> x; }
template <class T, class S> void read(pair<T, S> &v) {
read(v.first, v.second);
}
template <class T> void read(vector<T> &v) {
for (T &x : v)
read(x);
}
template <class T, class... Ts> void read(T &a, Ts &...b) {
read(a), read(b...);
}

void solve() {
int n, c;
cin >> n >> c;
vi dif(n);
string s;
cin >> s;
int cnt = 0;
rep(i, n) {
if (s[i] == s[n - 1 - i]) dif[i] = 0;
else dif[i] = 1, cnt++;
}
cnt /= 2;
vi h(n);
read(h);

vi p(n);
ll t = 0;
int w = 0;
int L = 1, R = 0;
auto add = [&](int x) {
if (!dif[x]) {
return;
}
int y = min(x, n - 1 - x);
p[y] += 1;
if (p[y] == 1) {
t += h[x];
w += 1;
} else {
t -= h[n - 1 - x];
t += min(h[x], h[n - 1 - x]);
}
};

auto del = [&](int x) {
if (!dif[x]) {
return;
}
int y = min(x, n - 1 - x);
p[y] -= 1;
if (p[y] == 0) {
t -= h[x];
w -= 1;
} else {
t -= min(h[x], h[n - 1 - x]);
t += h[n - 1 - x];
}
};


auto calc = [&](int l, int r) {
while (L > l) {
add(--L);
}
while (R < r) {
add(++R);
}
while (L < l) {
del(L++);
}
while (R > r) {
del(R--);
}
};

vc<ll> ans(n, lnf);
auto solve = [&](auto self, int l, int r, int a, int b) -> void {
if (l > r) {
return;
}
debug(l, r, a, b);
int m = (l + r) / 2;
int p = max(m, a);
calc(m, p);
while (p + 1 < n && w < cnt) {
p += 1;
calc(m, p);
}
if (w < cnt) {
self(self, l, m - 1, a, p);
return;
}
ll res = t + 1ll * (p - m) * c;
for (int i = p; i <= b; i++) {
calc(m, i);
if (res > t + 1ll * (i - m) * c) {
res = t + 1ll * (i - m) * c;
p = i;
}
}
cmin(ans[m], res);

self(self, l, m - 1, a, p);
self(self, m + 1, r, p, b);
};

t = 0, w = 0, L = 1, R = 0;
rep(i, n) p[i] = 0;
solve(solve, 0, n - 1, 0, n - 1);
reverse(all(ans));
reverse(all(h));
t = 0, w = 0, L = 1, R = 0;
rep(i, n) p[i] = 0;
solve(solve, 0, n - 1, 0, n - 1);
reverse(all(ans));
reverse(all(h));


ll mn = lnf;
for (int i = 0; i < n; i++) {
cmin(ans[i], mn + 1ll * i * c);
cmin(mn, ans[i] - 1ll * i * c);
}
reverse(all(ans));
mn = lnf;
for (int i = 0; i < n; i++) {
cmin(ans[i], mn + 1ll * i * c);
cmin(mn, ans[i] - 1ll * i * c);
}
reverse(all(ans));

for (auto x : ans) {
cout << x << " ";
}
cout << "\n";
}

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}

题解做法似乎可以做到 $O(n)$。

F. Beautiful Sequence

定义一个序列的美丽值为一个元素不小于他两侧的元素的个数。

没看懂题解。

G. Make Everything White

  • 不改变任何点
  • 改变他周围的点
  • 改变他周围的点和他自己

容易发现只用 2,3 操作就能完成。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <bits/stdc++.h>
#ifndef LOCAL
#define debug(...)
#else
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#endif
#define rep1(a) for (int i = 0; i < a; i++)
#define rep2(i, a) for (int i = 0; i < a; i++)
#define rep3(i, a, b) for (int i = a; i < b; i++)
#define rep4(i, a, b, c) for (int i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)

#define pb emplace_back
using namespace std;
template <typename T, typename T2> void cmin(T &x, const T2 &y) {
x = x < y ? x : y;
}
template <typename T, typename T2> void cmax(T &x, const T2 &y) {
x = x > y ? x : y;
}
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
template <class T> using vc = vector<T>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
mt19937 rng(time(NULL));
const int inf = 1000000000;
const ll lnf = 1000000000000000000;
#define sz(x) int((x).size())
#define all(x) begin(x), end(x)

template <class... T> void read() {}
template <class T> void read(T &x) { cin >> x; }
template <class T, class S> void read(pair<T, S> &v) {
read(v.first, v.second);
}
template <class T> void read(vector<T> &v) {
for (T &x : v)
read(x);
}
template <class T, class... Ts> void read(T &a, Ts &...b) {
read(a), read(b...);
}

void solve() {
int n, m;
read(n, m);
vc<string> a(n);
read(a);

vc<vi> b(n, vi(m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (a[i][j] == 'W') {
b[i][j] = 0;
} else {
b[i][j] = 1;
}
}
}

for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (i - 1 >= 0) b[i - 1][j] ^= 1;
if (i + 1 < n) b[i + 1][j] ^= 1;
if (j - 1 >= 0) b[i][j - 1] ^= 1;
if (j + 1 < m) b[i][j + 1] ^= 1;
}
}

cout << 1 << "\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << 2 + b[i][j];
}
cout << "\n";
}
}

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
// cin >> t;
while (t--) {
solve();
}
return 0;
}

I. Visiting Friend

圆方树,不会,队友切了。

J. Cooperation Game

删除 2 个相同颜色的位置,贡献是 $|i-j|$。求贡献的最大值。


首先显然的删除办法是相同颜色的第 $i$ 个和 $n-i+1$ 个匹配。

如果不相交,那么显然不关心顺序。

如果相交,那么至少要减掉相交对数。

所以直接计算即可。

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <bits/stdc++.h>
#ifndef LOCAL
#define debug(...)
#else
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#endif
#define rep1(a) for (int i = 0; i < a; i++)
#define rep2(i, a) for (int i = 0; i < a; i++)
#define rep3(i, a, b) for (int i = a; i < b; i++)
#define rep4(i, a, b, c) for (int i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, rep4, rep3, rep2, rep1)(__VA_ARGS__)

#define pb emplace_back
using namespace std;
template <typename T, typename T2> void cmin(T &x, const T2 &y) {
x = x < y ? x : y;
}
template <typename T, typename T2> void cmax(T &x, const T2 &y) {
x = x > y ? x : y;
}
using ll = long long;
using vi = vector<int>;
using pii = pair<int, int>;
template <class T> using vc = vector<T>;
template <class T> using pq = priority_queue<T>;
template <class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
mt19937 rng(time(NULL));
const int inf = 1000000000;
const ll lnf = 1000000000000000000;
#define sz(x) int((x).size())
#define all(x) begin(x), end(x)

template <class... T> void read() {}
template <class T> void read(T &x) { cin >> x; }
template <class T, class S> void read(pair<T, S> &v) {
read(v.first, v.second);
}
template <class T> void read(vector<T> &v) {
for (T &x : v)
read(x);
}
template <class T, class... Ts> void read(T &a, Ts &...b) {
read(a), read(b...);
}
template <typename T> struct Fenwick {
int n;
std::vector<T> a;

Fenwick(int n = 0) { init(n); }

void init(int n) {
this->n = n;
a.assign(n, T());
}

void add(int x, T v) {
for (int i = x + 1; i <= n; i += i & -i) {
a[i - 1] += v;
}
}

T sum(int x) {
auto ans = T();
for (int i = x; i > 0; i -= i & -i) {
ans += a[i - 1];
}
return ans;
}

T rangeSum(int l, int r) { return sum(r) - sum(l); }

int kth(T k) {
int x = 0;
for (int i = 1 << std::__lg(n); i; i /= 2) {
if (x + i <= n && k >= a[x + i - 1]) {
x += i;
k -= a[x - 1];
}
}
return x;
}
};
void solve() {
int n;
cin >> n;
vi a(n);
read(a);
for (int i = 0; i < n; i++) {
--a[i];
}

vc<vi> v(n);
rep(i, n) v[a[i]].pb(i);
vc<pii> seg;
rep(val, n) {
int i = 0;
int j = sz(v[val]) - 1;
while (i < j) {
seg.pb(v[val][i], v[val][j]);
i++;
j--;
}
}

sort(all(seg));

Fenwick<int> f(n);
long long ans = 0;
for (auto [l, r] : seg) {
ans += r - l;
ans -= f.rangeSum(l, r + 1);
f.add(r, 1);
}

cout << ans << "\n";
}

int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
cin >> t;
while (t--) {
solve();
}
return 0;
}

K. Connect the Dots

有 N 个点,每个点有一个颜色。

一个匹配 $(i, j)$,$c_i \neq c_j$。

$(i, j)$ 区间不相交,最大匹配数。


咕咕咕。