Educational Codeforces Round 101 (Rated for Div. 2)
Educational Codeforces Round 101 (Rated for Div. 2)
A - Regular Bracket Sequence
最多有一对 (), 判断完事
int main() {
IOS;
for (cin >> _; _; --_) {
string s; cin >> s;
if (s.size() % 2 || s[0] == ')' || s.back() == '(') cout << "NO\n";
else cout << "YES\n";
}
return 0;
}
B - Red and Blue
贪心找两个序列的最大前缀和
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; int x = 0, y = 0;
for (int s = 0, i = 1; i <= n; ++i) cin >> k, s += k, umax(x, s);
cin >> n;
for (int s = 0, i = 1; i <= n; ++i) cin >> k, s += k, umax(y, s);
cout << x + y << '\n';
}
return 0;
}
C - Building a Fence
按顺序找出当前 i 可以放的最高和最低位置, 再按提议判断即可
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> k >> m;
int x = m, y = m; bool f = 1;
rep (i, 2, n) {
cin >> m;
x = min(x + k - 1, m + k - 1);
y = max(y - k + 1, m);
if (x < y) f = 0;
}
if (y != m || !f) cout << "NO\n";
else cout << "YES\n";
}
return 0;
}
D - Ceil Divisions
明显能想到一个数用比它大的数变成 1, 但剩下最大数无法处理
只给你了n + 5, 明显让你在5次之内变成 1, 而 sqrt(n - 1) + 1 刚好 2 次
然后 sqrt(n - 1) + 1 成为了最大数, 在按上面操作, 而最多开5次根号, 刚刚好(1, 2还不用变呢 n + 3就够了)
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; VI a(1, n);
while (a.back() != 2) a.pb(sqrt(a.back() - 1) + 1);
cout << n - 3 + a.size() << '\n';
for (int i = n, j = 0; i > 2; --i)
if (i == a[j]) ++j;
else cout << i << ' ' << n << '\n';
rep (i, 1, a.size() - 1) rep (j, 0, 1) cout << a[i - 1] << ' ' << a[i] << '\n';
}
return 0;
}
E - A Bit Similar
一看字符串里找字符串就先把 sam 板子仍上去, 然而1e6 咋办呢
最多有1e6个字串, 也就是说最多能完全覆盖长度为 log2(1e6) 的01串, 在sam上贪心爆搜完事
当然肯定有不用sam的方法, div2不怎么考数据结构的, 能用板子直接扔最好了
struct SAM { //不管是不是多组数据都调用init
static const int N = 1e6 + 5, M = 2;
struct node { int fa, len, ne[M]; } tr[N << 1];
int sz, las;
void init() {
rep(i, 1, sz)
tr[i].len = tr[i].fa = 0, memset(tr[i].ne, 0, sizeof tr[i].ne);
sz = las = 1;
}
void add(int ch) {
int p = las, cur = las = ++sz;
tr[cur].len = tr[p].len + 1;
for (; p && !tr[p].ne[ch]; p = tr[p].fa) tr[p].ne[ch] = cur;
if (p == 0) { tr[cur].fa = 1; return; }
int q = tr[p].ne[ch];
if (tr[q].len == tr[p].len + 1) { tr[cur].fa = q; return; }
int nq = ++sz; tr[nq] = tr[q]; tr[nq].len = tr[p].len + 1;
for (; p && tr[p].ne[ch] == q; p = tr[p].fa) tr[p].ne[ch] = nq;
tr[q].fa = tr[cur].fa = nq;
}
void build(char* s) {
for (int i = 0; s[i]; ++i) add(s[i] - '0');
}
bool match(char* s) {
for (int i = 0, ch = s[i] - '0', p = 1; s[i]; ch = s[++i] - '0')
if (tr[p].ne[ch]) p = tr[p].ne[ch];
else return 0;
return 1;
}
} sam;
const int N = 1e6 + 5;
int n, m, _, k;
char s[N], t[N];
bool check(int x = 0) {
if (x == k) { t[x] = '\0'; return !sam.match(t); }
t[x] = '1';
if (check(x + 1)) return 1;
t[x] = '0';
return check(x + 1);
}
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> k >> s;
if (n == k) {
cout << "YES\n"; bool f = 0;
rep (i, 0, n - 2) f = f || s[i] == '0', s[i] = '0';
if (f) s[n - 1] = '0';
cout << s << '\n';
continue;
}
m = log2(n - k) + 1; sam.init(); sam.build(s);
if (!check()) { cout << "NO\n"; continue; }
cout << "YES\n";
for (int i = 0; t[i]; ++i) t[i] = t[i] - '0' ? '0' : '1';
rep(i, 0, k - 1) if (!t[i]) t[i] = '0'; t[n] = '\0';
cout << t << '\n';
}
return 0;
}
F - Power Sockets
还是板子题, 贪心放就好了, 去出没用过的链, 平分两份, 放在树上深度最小的点上, 找就行了
复杂度 \(O(nlog^2n)\) 4s够了
ll c[2][N + 1], ans = 2e18;
void add(int x, ll k) {
for (int i = x; i <= N; i += -i & i) c[0][i] += k, c[1][i] += x * k;
}
void add(int l, int r, ll k) { add(l, k); add(r + 1, -k); }
ll ask(int x) {
ll p = 0, q = 0, f = x + 1;
for (; x; x -= -x & x) p += c[0][x], q += c[1][x];
return p * f - q;
}
ll ask(int l, int r) { return ask(r) - ask(l - 1); }
ll kth(int k) {
if (ask(N) < k) return 2e18;
int l = 1, r = N;
while (l < r) {
ll mid = l + r >> 1, c;
if ((c = ask(l, mid)) < k) k -= c, l = mid + 1;
else r = mid;
}
return l;
}
int main() {
IOS; cin >> n >> k; VI a(n);
for (auto &i : a) cin >> i, --i; sort(all(a));
add(2, 2 + a.back() >> 1, 1); add(2, 2 + a.back() + 1 >> 1, 1); umin(ans, kth(k));
per (i, n - 2, 0) {
int cur = kth(1); add(cur, cur, -1);
add(cur + 2, 1 + cur + (a[i] >> 1), 1); add(cur + 2, 1 + cur + (a[i] + 1 >> 1), 1);
umin(ans, kth(k));
}
cout << (ans == 2e18 ? -1 : ans);
return 0;
}