Educational Codeforces Round 97 (Rated for Div. 2)

A

在 l ~ r 之间肯定不行

当 a > r, 则 l >= a/2 即 r < a <= 2l, 即 r < 2l

当 a < l, 则 (lfloor frac{r}{lfloor frac{a}{2} floor} floor - lfloor frac{l-1}{lfloor frac{a}{2} floor} floor ≡ 0), 即 r - l + 1 < a / 2 即 2r - 2l + 2 < a < l

即 2r - 2l + 2 + 1 < l 即 (frac{2}{3})r + 1 < l 即 (frac{1}{3})r < a/2 然而 a < l <= r 故 a < l 命题错误

int main() {
    IOS;
    for (cin >> _; _; --_) {
        ll a, b; cin >> a >> b;
        if (a * 2 > b) cout << "YES
";
        else cout << "NO
";
    } 
    return 0;
}

B

每次操作 消除一个 00 或 11

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n; cin >> s + 1;
        int ans = 0, cur = 0;
        rep (i, 2, n) 
            if (s[i] == s[i - 1]) ++ans;
        cout << (ans + 1) / 2 << '
';
    } 
    return 0;
}

C

01背包

dp, 背包容量为 2n (即所有物品从 n 开始放 放到 2n - 1), 你不会把 n 个物品疯狂往后放吧, 肯定不是最小值

int main() {
    IOS;
    for (cin >> _; _; --_) {
        cin >> n;
        rep(i, 1, n) cin >> a[i];
        sort(a + 1, a + 1 + n);
        rep(j, 1, n) f[j] = 1e15;
        rep(i, 1, n << 1)
            per(j, min(n, i), 1) 
                umin(f[j], f[j - 1] + abs(i - a[j]));
        cout << f[n] << '
';
    }
    return 0;
}

D

我是sb, 我是sb, 我是sb

脑子没转过来弯

连续递增的一段可以作为 兄弟节点

其之后的每个连续段(即兄弟节点), 可以依次放在 前一段递增序列 的下面, 作为其子节点

(就是这里,我卡住了, 为啥能依次放啊? 我一直卡在只能放在 前一段递增序列 的最后一个节点上, 怎么着都转不过来弯)

我是sb, 我是sb, 我是sb

int main() {
    IOS; a[1] = 1; 
    for (cin >> _; _; --_) {
        cin >> n >> m;
        rep (i, 2, n) {
            cin >> a[i];
            if (a[i] < a[i - 1]) ++m;
            h[i] = h[m] + 1;
        }
        cout << h[n] << '
';
    }
    return 0;
}

E

单独写开了

G

为啥不敢去看G啊, 原来难度不一定递增啊

这tm就是一道 AC自动机裸体, 改一点点就行, 可以看看我置顶的 字符串 板子

这就是套板子完事, 思维也没考, 就考个数据结构, 这也能放在G....

struct AC {
    static const int N = 3e5 + 5, M = 26, C = 'a'; //字符串总长度, 字符范围
 
    int trie[N][M], cnt[N], fail[N], vis[N], tot;
    vector<multiset<int>> idx; //记录节点结尾的字符串id的权值
    int q[N], idn[N], mx[N];
 
    void init() {
        idx.resize(1, multiset<int>());
    }
 
    int newnode() {
        idx.pb(multiset<int>());
        mx[++tot] = -1;
        return tot;
    }
 
    void insert(char* s, int id) {
        int p = 0;
        for (int i = 0; s[i]; ++i) {
            int ch = s[i] - C;
            if (!trie[p][ch]) trie[p][ch] = newnode();
            p = trie[p][ch];
        }
        ++cnt[p]; idn[id] = p;
        idx[p].insert(0);
        mx[p] = 0;
    }
 
    void build() {
        int head = 0, tail = -1;
        rep(i, 0, M - 1) if (trie[0][i]) q[++tail] = trie[0][i];
        while (head <= tail) {
            int p = q[head++];
            rep(i, 0, M - 1)
                if (trie[p][i])
                    fail[trie[p][i]] = trie[fail[p]][i], q[++tail] = trie[p][i];
                else trie[p][i] = trie[fail[p]][i];
        }
    }
 
    int query(char* s) {
        set<int> v;
        int p = 0, res = -1;
        for (int i = 0; s[i]; ++i) {
            p = trie[p][s[i] - C];
            for (int tmp = p; tmp && !v.count(tmp); tmp = fail[tmp]) {
                umax(res, mx[tmp]); v.insert(tmp);
            }
        }
        return res;
    }
 
    void change(int id, int k, int yk) {
        int p = idn[id];
        idx[p].erase(idx[p].find(yk)); idx[p].insert(k);
        mx[p] = *idx[p].rbegin();
    }
} ac;
 
const int N = 3e5 + 5;
 
int n, m;
int a[N];
char s[N];
 
int main() {
    IOS; cin >> n >> m; ac.init();
    rep(i, 1, n) cin >> s, ac.insert(s, i);
    ac.build();
    rep(i, 1, m) {
        int op; cin >> op;
        if (op == 2) {
            cin >> s;
            cout << ac.query(s) << '
';
        }
        else {
            int k, s; cin >> k >> s;
            ac.change(k, s, a[k]); a[k] = s;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/13897304.html