We (the setters) hope you liked the problems. Here is the editorial:
Tutorial is loading...
C++ solution
#include <iostream>
#define endl '\n'
using namespace std;
void solve()
{
int n;
cin >> n;
string s(200, 'a');
cout << s << endl;
for (int i = 0; i < n; ++i)
{
int u;
cin >> u;
s[u] = s[u] == 'a' ? 'b' : 'a';
cout << s << endl;
}
}
int main()
{
int t;
cin >> t;
for (int i = 0; i < t; ++i)
{
solve();
}
return 0;
}
Python solution
import sys
input = sys.stdin.readline
def main():
t = int(input())
for _ in range(t):
n = int(input())
a = list(map(int, input().split()))
mx = max(a)
ans = [ 'a' * (mx + 1) ] * (n + 1)
for i, x in enumerate(a):
who = 'a' if ans[i][x] == 'b' else 'b'
ans[i + 1] = ans[i][:x] + who + ans[i][x + 1:]
print('\n'.join(ans))
main()
Problem idea: dcordb
Solution idea: dcordb and Devil
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(0), cin.tie(0);
int test;
cin >> test;
while (test--)
{
int n, k, l;
cin >> n >> k >> l;
vector<int> d(n+2, -k);
for (int i = 1; i <= n; ++i)
cin >> d[i];
set<tuple<int, int, bool>> mark;
function<bool(int, int, bool)> go = [&](int pos, int tide, bool down)
{
if (pos > n) return true;
if (mark.find({ pos, tide, down }) != mark.end())
return false;
mark.insert({ pos, tide, down });
tide += down ? -1 : +1;
if (tide == 0) down = false;
if (tide == k) down = true;
if (d[pos] + tide <= l && go(pos, tide, down))
return true;
if (d[pos + 1] + tide <= l && go(pos + 1, tide, down))
return true;
return false;
};
if (go(0, 0, false)) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}
Problem idea: Devil
Solution idea: Devil
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(0), cin.tie(0);
int test;
cin >> test;
while (test--)
{
int n, k, l;
cin >> n >> k >> l;
vector<int> d(n+1), safe = { 0 };
for (int i = 1; i <= n; ++i)
{
cin >> d[i];
if (d[i] + k <= l)
safe.push_back(i);
}
safe.push_back(n+1);
bool ok = true;
for (size_t i = 1; i < safe.size() && ok; ++i)
{
int tide = k; bool down = true;
for (int j = safe[i-1] + 1; j < safe[i]; ++j)
{
tide += down ? -1 : +1;
if (down) tide -= max(0, d[j] + tide - l);
if (tide < 0 || d[j] + tide > l) { ok = false; break; }
if (tide == 0) down = false;
}
}
if (ok) cout << "Yes\n";
else cout << "No\n";
}
return 0;
}
Problem idea: Devil
Solution idea: Devil
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
const int Alp = 20;
int main()
{
ios_base::sync_with_stdio(0), cin.tie(0);
int test;
cin >> test;
while (test--)
{
int n;
string a, b;
cin >> n >> a >> b;
bool bad = false;
vector<vector<int>> adj(Alp);
for (int i = 0; i < n; ++i)
if (a[i] != b[i])
{
if (a[i] > b[i])
{
bad = true;
cout << "-1\n";
break;
}
adj[a[i]-'a'].push_back(b[i]-'a');
adj[b[i]-'a'].push_back(a[i]-'a');
}
if (bad) continue;
vector<bool> mark(Alp);
function<void(int)> dfs = [&](int u)
{
mark[u] = true;
for (auto v : adj[u])
if (!mark[v])
dfs(v);
};
int ans = Alp;
for (int i = 0; i < Alp; ++i)
if (!mark[i])
dfs(i), --ans;
cout << ans << "\n";
}
return 0;
}
Problem idea: Devil
Solution idea: mnaeraxr and Devil
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(0), cin.tie(0);
int test;
cin >> test;
while (test--)
{
int n;
cin >> n;
int x = 0;
vector<int> a(n);
for (auto &i : a)
{
cin >> i;
x ^= i;
}
if (x == 0)
{
cout << "DRAW\n";
continue;
}
for (int k = 30; k >= 0; --k)
if (x >> k & 1)
{
vector<int> f(2);
for (auto &i : a) ++f[i >> k & 1];
if (f[1] % 4 == 3 && f[0] % 2 == 0)
cout << "LOSE\n";
else
cout << "WIN\n";
break;
}
}
return 0;
}
Python solution
import sys
input = sys.stdin.readline
d = { 1: 'WIN', 0: 'LOSE', -1: 'DRAW' }
def main():
t = int(input())
for _ in range(t):
n = int(input())
a = map(int, input().split())
f = [0] * 30
for x in a:
for b in range(30):
if x >> b & 1:
f[b] += 1
ans = -1
for x in reversed(range(30)):
if f[x] % 2 == 1:
ans = 0 if f[x] % 4 == 3 and (n - f[x]) % 2 == 0 else 1
break
print(d[ans])
main()
Problem idea: Devil
Solution idea: Devil and dcordb
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
const int Alp = 20;
int main()
{
ios_base::sync_with_stdio(0), cin.tie(0);
int test;
cin >> test;
while (test--)
{
int len;
string a, b;
cin >> len >> a >> b;
vector<int> adj(Alp);
vector<vector<int>> G(Alp);
for (int i = 0; i < len; ++i)
if (a[i] != b[i])
{
adj[a[i]-'a'] |= 1 << (b[i]-'a');
G[a[i]-'a'].push_back(b[i]-'a');
G[b[i]-'a'].push_back(a[i]-'a');
}
vector<bool> mark(Alp);
function<void(int)> dfs = [&](int u)
{
mark[u] = true;
for (auto v : G[u])
if (!mark[v])
dfs(v);
};
int comp = 0;
for (int i = 0; i < Alp; ++i)
if (!mark[i])
dfs(i), ++comp;
int ans = 0;
vector<bool> dp(1<<Alp);
dp[0] = true;
for (int mask = 0; mask < 1<<Alp; ++mask)
if (dp[mask])
{
ans = max(ans, __builtin_popcount(mask));
for (int u = 0; u < Alp; ++u)
if ((~mask >> u & 1) && (adj[u] & mask) == 0)
dp[mask | 1 << u] = true;
}
cout << 2*Alp - comp - ans << "\n";
}
return 0;
}
Problem idea: Devil
Solution idea: mnaeraxr
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
int n, m;
cin >> n >> m;
vector<vector<int>> mat(n, vector<int>(m));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cin >> mat[i][j];
vector<int> h(n * m + 1);
vector<int> v(n * m + 1);
for (int i = 0; i < n; ++i)
{
int a = 0;
for (int j = 0; j < m; ++j)
a = max(a, mat[i][j]);
h[a] = 1;
}
for (int i = 0; i < m; ++i)
{
int a = 0;
for (int j = 0; j < n; ++j)
a = max(a, mat[j][i]);
v[a] = 1;
}
vector<vector<int>> fin(n, vector<int>(m));
queue<pair<int, int>> q;
int x = -1, y = -1;
for (int u = n * m; u >= 1; --u)
{
x += h[u];
y += v[u];
if (h[u] || v[u])
{
fin[x][y] = u;
}
else
{
int qx, qy;
tie(qx, qy) = q.front();
q.pop();
fin[qx][qy] = u;
}
if (h[u])
for (int i = y - 1; i >= 0; --i)
q.push({x, i});
if (v[u])
for (int i = x - 1; i >= 0; --i)
q.push({i, y});
}
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
cout << fin[i][j] << " \n"[j + 1 == m];
return 0;
}
Problem idea: gilcu3
Solution idea: gilcu3 and mnaeraxr
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int main()
{
ios::sync_with_stdio(false), cin.tie(0);
string s; cin >> s;
int n = s.length();
vector<int> dist(n);
for (int i = 0; i < n; ++i)
if (s[i] == '0') dist[i] = (i ? dist[i-1] : 0) + 1;
vector<int> dp(n + 2), nxt(n+2, n);
auto get = [&](int i) { return nxt[i] < n ? dp[nxt[i]] : 0; };
for (int i = n-1; i >= 0; --i)
{
dp[i] = ((dist[i] <= dist.back()) + get(0) + get(dist[i] + 1)) % mod;
nxt[dist[i]] = i;
}
int ans = n;
if (nxt[0] < n)
ans = ((long long)get(0) * (nxt[0] + 1)) % mod;
cout << ans << "\n";
return 0;
}
Problem idea: Devil
Solution idea: Devil and antontrygubO_o
Tutorial is loading...
C++ solution
#include <bits/stdc++.h>
using namespace std;
template<typename C, typename R = C>
struct dinic
{
typedef C flow_type;
typedef R result_type;
static_assert(std::is_arithmetic<flow_type>::value, "flow_type must be arithmetic");
static_assert(std::is_arithmetic<result_type>::value, "result_type must be arithmetic");
static const flow_type oo = std::numeric_limits<flow_type>::max();
struct edge
{
//int src; // not needed, can be deleted to save memory
int dst;
int rev;
flow_type cap, flowp;
edge(int src, int dst, int rev, flow_type cap, int flowp) :
/*src(src),*/ dst(dst), rev(rev), cap(cap), flowp(flowp) {}
};
dinic(int n) : adj(n), que(n), level(n), edge_pos(n), flow_id(0) {}
int add_edge(int src, int dst, flow_type cap, flow_type rcap = 0)
{
adj[src].emplace_back(src, dst, (int) adj[dst].size(), cap, flow_id++);
if (src == dst) adj[src].back().rev++;
adj[dst].emplace_back(dst, src, (int) adj[src].size() - 1, rcap, flow_id++);
return (int) adj[src].size() - 1 - (src == dst);
}
inline bool side_of_S(int u) { return level[u] == -1; }
result_type max_flow(int source, int sink, vector<flow_type> &flow_e)
{
result_type flow = 0;
while (true)
{
int front = 0, back = 0;
std::fill(level.begin(), level.end(), -1);
for (level[que[back++] = sink] = 0; front < back && level[source] == -1; ++front)
{
int u = que[front];
for (const edge &e : adj[u])
if (level[e.dst] == -1 && flow_e[rev(e).flowp] < rev(e).cap)
level[que[back++] = e.dst] = 1 + level[u];
}
if (level[source] == -1)
break;
std::fill(edge_pos.begin(), edge_pos.end(), 0);
std::function<flow_type(int, flow_type)> find_path = [&](int from, flow_type res)
{
if (from == sink)
return res;
for (int &ept = edge_pos[from]; ept < (int) adj[from].size(); ++ept)
{
edge &e = adj[from][ept];
if (flow_e[e.flowp] == e.cap || level[e.dst] + 1 != level[from]) continue;
flow_type push = find_path(e.dst, std::min(res, e.cap - flow_e[e.flowp]));
if (push > 0)
{
flow_e[e.flowp] += push;
flow_e[rev(e).flowp] -= push;
if (flow_e[e.flowp] == e.cap)
++ept;
return push;
}
}
return static_cast<flow_type>(0);
};
for (flow_type f; (f = find_path(source, oo)) > 0;)
flow += f;
}
return flow;
}
result_type max_flow2(int source, int sink, vector<flow_type> &flow_e)
{
result_type flow = 0;
std::function<flow_type(int, flow_type)> find_path = [&](int from, flow_type res)
{
level[from] = 1;
if (from == sink)
return res;
for (int &ept = edge_pos[from]; ept < (int) adj[from].size(); ++ept)
{
edge &e = adj[from][ept];
if (level[e.dst] == 1 || flow_e[e.flowp] == e.cap) continue;
flow_type push = find_path(e.dst, std::min(res, e.cap - flow_e[e.flowp]));
if (push > 0)
{
flow_e[e.flowp] += push;
flow_e[rev(e).flowp] -= push;
if (flow_e[e.flowp] == e.cap)
++ept;
return push;
}
}
return static_cast<flow_type>(0);
};
for (bool ok = true; ok; )
{
int it = 0;
std::fill(edge_pos.begin(), edge_pos.end(), 0);
for (flow_type f; ; ++it)
{
std::fill(level.begin(), level.end(), -1);
f = find_path(source, oo);
if (f == 0)
{
if (it == 0) ok = false;
break;
}
flow += f;
}
}
return flow;
}
int flow_id;
private:
std::vector<std::vector<edge>> adj;
std::vector<int> que;
std::vector<int> level;
std::vector<int> edge_pos;
inline edge& rev(const edge &e) { return adj[e.dst][e.rev]; }
};
const int inf = 25;
struct edge
{
int u, v, w;
};
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
void relabel(int n, vector<edge> &e, int k)
{
shuffle(e.begin() + k, e.end(), rng);
vector<vector<pair<int, int>>> adj(n);
for (auto &i : e)
adj[i.u].push_back({ i.v, &i-&e[0] });
vector<edge> ne = e;
vector<int> id(n, -1);
id[0] = 0;
id[n-1] = n-1;
int sz = 1, esz = k;
function<void(int)> dfs = [&](int u)
{
for (auto &v : adj[u])
{
if (v.second >= k)
{
ne[esz++] = e[v.second];
v.second = -1;
}
if (id[v.first] == -1)
{
id[v.first] = sz++;
dfs(v.first);
}
}
};
dfs(0);
for (auto &u : adj)
for (auto v : u)
if (v.second >= k)
ne[esz++] = e[v.second];
for (int i = 0; i < n; ++i)
if (id[i] == -1)
id[i] = sz++;
e = ne;
for (auto &i : e)
{
i.u = id[i.u];
i.v = id[i.v];
}
}
struct masks
{
int x, cost;
vector<int> flow_e;
bool operator<(const masks &o) const
{
return cost < o.cost;
}
};
typedef std::chrono::_V2::system_clock::time_point timepoint;
timepoint get_time()
{
return std::chrono::high_resolution_clock::now();
}
int get_elapsed(timepoint t)
{
return std::chrono::duration_cast<std::chrono::milliseconds>(get_time() - t).count();
}
int main()
{
ios_base::sync_with_stdio(0), cin.tie(0);
int n, m, k, q;
cin >> n >> m >> k >> q;
vector<edge> e(m);
for (auto &i : e) cin >> i.u >> i.v >> i.w, --i.u, --i.v;
vector<int> mask(1 << k, -1);
relabel(n, e, k);
dinic<int> d(n);
for (int i = 0; i < m; ++i)
d.add_edge(e[i].u, e[i].v, ((i < k) ? inf : e[i].w));
vector<int> flow_e(d.flow_id);
for (int i = 0; i < k; ++i)
flow_e[2*i] = inf;
mask[0] = d.max_flow(0, n-1, flow_e);
priority_queue<masks> pq;
pq.push({ 0, 0, flow_e });
while (!pq.empty())
{
int x = pq.top().x;
flow_e = pq.top().flow_e;
pq.pop();
for (int j = 0; j < k; ++j)
if ((~x >> j & 1) && mask[x | 1 << j] == -1)
{
auto n_flow_e = flow_e;
n_flow_e[2 * j] = 0;
auto t = get_time();
mask[x | 1 << j] = mask[x] + d.max_flow2(0, n-1, n_flow_e);
pq.push({ x | 1 << j, get_elapsed(t), n_flow_e });
}
}
vector<int> cut(1 << k), bit(1 << k);
for (int i = 1; i < 1 << k; ++i)
bit[i] = i & -i;
const int U = (1 << k) - 1;
while (q--)
{
for (int i = 0; i < k; ++i)
cin >> cut[1 << i];
int ans = mask[U];
for (int i = 1; i < 1<<k; ++i)
{
cut[i] = cut[i ^ bit[i]] + cut[bit[i]];
ans = min(ans, cut[i] + mask[U ^ i]);
}
cout << ans << "\n";
}
return 0;
}
Problem idea: mnaeraxr