牛客练习赛80
牛客练习赛80
A - 加密
要么拼接两个\('1'\)串, 要么把一个长度为\(1\)的\('1'\)串改为\('0'\)
int main() {
IOS; string s; cin >> s; s += '0';
rep (i, 0, s.size() - 1) {
if (s[i] == '0') {
if (k == 1) m = 1, ++n, k = 0;
else if (k) ++n, k = 0, _ = i - 1;
}
else ++k;
if (k == 1 && i - _ == 2) m = 1;
}
cout << n - m;
return 0;
}
B - 卷积
发现
\({ mex(x, y) = 0 | min(x, y) > 0}\)
\({ mex(0, y) = mex(x, 0) = 1 | min(x, y) != 1}\)
\(mex(0, 1) = mex(1, 0) = 2\)
\(mex(x, y) < 3\)
则
\(c[0] = \sum_{i = 1}^{n - 1} a_i \times (\sum b_j - b_0)\)
\(c[1] = a_0 \times (\sum b_j - b_1) + b_0 \times (\sum a_i - a_0 - a_1)\)
\(c[2] = a_0 \times b_1 + a_1 \times b_0\)
\(c[i] = 0, i > 2\)
代码下标从1开始
int main() {
IOS; cin >> n;
rep (i, 1, n) cin >> a[i], x[i] = (x[i - 1] + a[i]) % mod;
rep (i, 1, n) cin >> b[i], y[i] = (y[i - 1] + b[i]) % mod;
rep (i, 2, n) c[1] = (c[1] + a[i] * (y[n] - y[1]) % mod) % mod;
c[2] = (a[1] * (y[n] - b[2]) % mod + b[1] * (x[n] - x[2]) % mod) % mod;
c[3] = (a[1] * b[2] % mod + a[2] * b[1] % mod) % mod;
rep (i, 1, 3) c[i] = (c[i] + mod) % mod;
rep (i, 1, n) cout << c[i] << ' ';
return 0;
}
C - 不降数
隔板法, n个数, 在板子\(k(0<k<10)\) 到板子\(k-1\)之间的数字为\(k\)
强制把第\(0、9\)块板子放在最前、后, 保证, 每个数都在选中
答案就是\(C_{n + 8}^{8}\)
ll qpow(ll a, ll b) {
ll ans = 1;
for (; b; b >>= 1, a = a * a % mod) if (b & 1) ans = ans * a % mod;
return ans;
}
int main() {
IOS; cin >> n; ll c = 1, ans = 1;
rep (i, 1, 8) c = c * i % mod, ans = (n + i) % mod * ans % mod;
cout << ans * qpow(c, mod - 2) % mod;
return 0;
}
D - 分组
倍增即可, 用\(tarjan\)缩点找强连通分量 \(O(mlog(m))\)
int n, m, _, k, cas;
int dfn[N], low[N], df, st[N], top, l[N * 10], r[N * 10];
vector<int> h[N];
long long res;
bool inst[N];
void tarjan(int x) {
dfn[x] = low[x] = ++df, inst[st[++top] = x] = 1;
for (auto &y : h[x])
if (!dfn[y]) tarjan(y), umin(low[x], low[y]);
else if (inst[y]) umin(low[x], dfn[y]);
if (dfn[x] == low[x]) {
int c = 0;
do inst[st[top]] = 0, ++c; while (st[top--] ^ x);
res += 1ll * c * c;
}
}
bool check(int L, int R) {
vector<int> p; res = n;
rep (i, L, R) h[l[i]].pb(r[i]), p.pb(l[i]), p.pb(r[i]), dfn[l[i]] = dfn[r[i]] = 0;
for (auto &x : p) if (!dfn[x]) top = df = 0, tarjan(x), res -= df;
rep (i, L, R) h[l[i]].pop_back(); return res <= k;
}
int main() {
IOS; cin >> n >> m >> k;
rep (i, 1, m) cin >> l[i] >> r[i];
for (int l = 1, j = 1, r = 1, f = 0; l <= m; l = ++r, j = 1, ++_, f = 0) while (j && r < m)
if (r + j <= m && check(l, r + j)) j <<= 1, f = 1;
else { if (f) r += j >> 1, j >>= 2; else j >>= 1; f = 0; }
cout << _;
return 0;
}
E - 覆盖
离线回答即可, 按询问的\(r\)排序, 用线段树数维护当前区间的覆盖情况, 用树状数组维护当前每个左端点\(l\)到当前的\(r\)的答案
const int N = 2e5 + 5;
struct BIt {
struct node { int l, r, len, ls, tag; } tr[N * 20];
ll c[N], n;
void add(int x, int k) { for (; x <= n; x += -x & x) c[x] += k; }
ll ask(int x) { ll ans = 0; for (; x; x -= -x & x) ans += c[x]; return ans; }
void push_up(int rt) { if (tr[rt << 1].ls == tr[rt << 1 | 1].ls) tr[rt].ls = tr[rt << 1].ls; }
void push_down(int rt) {
if (!tr[rt].tag) return;
tr[rt << 1].ls = tr[rt << 1 | 1].ls = tr[rt].tag;
tr[rt << 1].tag = tr[rt << 1 | 1].tag = tr[rt].tag;
tr[rt].tag = 0;
}
void build(int rt, int l, int r, VI& c) {
tr[rt].l = l, tr[rt].r = r; tr[rt].len = c[r + 1] - c[l];
if (l == r) return; int mid = l + r >> 1;
build(rt << 1, l, mid, c); build(rt << 1 | 1, mid + 1, r, c);
}
void change(int rt, int l, int r, int ls) {
if (tr[rt].l >= l && tr[rt].r <= r && ~tr[rt].ls) {
add(tr[rt].ls + 1, tr[rt].len); add(ls + 1, -tr[rt].len);
tr[rt].ls = tr[rt].tag = ls; return;
}
tr[rt].ls = -1; push_down(rt); int mid = tr[rt].l + tr[rt].r >> 1;
if (mid >= l) change(rt << 1, l, r, ls);
if (mid < r) change(rt << 1 | 1, l, r, ls);
push_up(rt);
}
} bit;
struct node { int l, r, k; } b[N];
int n, m, _, k, cas;
PII a[N];
int ans[N];
int main() {
IOS; cin >> n >> m; VI c;
rep (i, 1, n) cin >> a[i].fi >> a[i].se, c.pb(a[i].fi), c.pb(++a[i].se);
rep (i, 1, m) cin >> b[i].l >> b[i].r, b[i].k = i;
sort(all(c)); c.erase(unique(all(c)), c.end());
sort(b + 1, b + 1 + m, [](node& a, node& b) { return a.r < b.r; });
rep (i, 1, n)
a[i].fi = lower_bound(all(c), a[i].fi) - c.begin(),
a[i].se = lower_bound(all(c), a[i].se) - c.begin() - 1;
bit.n = n; bit.build(1, 0, c.size() - 2, c);
for (int i = 1, j = 0; i <= m; ++i) {
while (j < b[i].r) ++j, bit.change(1, a[j].fi, a[j].se, j);
ans[b[i].k] = bit.ask(b[i].l);
}
rep (i, 1, m) cout << ans[i] << '\n';
return 0;
}