牛客练习赛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 imes (sum b_j - b_0))

(c[1] = a_0 imes (sum b_j - b_1) + b_0 imes (sum a_i - a_0 - a_1))

(c[2] = a_0 imes b_1 + a_1 imes 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] << '
';
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/14641782.html