• Codeforces #452 Div2 F


    #452 Div2 F

    题意

    给出一个字符串, m 次操作,每次删除区间 ([l,r]) 之间的字符 (c) ,输出最后得到的字符串。

    分析

    通过树状数组和二分,我们可以把给定的区间对应到在起始字符串上的区间。
    然后暴力去删字符即可(因为最多只会删掉等同于字符串长度的字符个数),总共只有 62 种字符,set 维护下位置。

    code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 4e5 + 10;
    int n, m, f[N];
    void update(int x) {
        for(int i = x; i < N; i += i & -i) f[i]--;
    }
    int query(int x) {
        int s = 0;
        for(int i = x; i; i -= i & -i) s += f[i];
        return s;
    }
    int fd(int x) {
        int l = 1, r = n, mid;
        while(l < r) {
            mid = l + r >> 1;
            if(query(mid) < x) l = mid + 1;
            else r = mid;
        }
        return l;
    }
    char s[N];
    set<int> S[150];
    char ans[N];
    int main() {
        scanf("%d%d", &n, &m);
        scanf("%s", s + 1);
        for(int i = 1; i <= n; i++) {
            S[s[i]].insert(i);
            f[i + (i & -i)] += ++f[i];
        }
        while(m--) {
            char c[2];
            int l, r;
            scanf("%d%d%s", &l, &r, c);
            l = fd(l);
            r = fd(r);
            auto it = S[c[0]].lower_bound(l);
            while(it != S[c[0]].end() && *it <= r) {
                update(*it);
                auto itt = it;
                it++;
                S[c[0]].erase(itt);
            }
        }
        for(int i = 0; i < 150; i++) {
            for(int j : S[i]) ans[j] = i;
        }
        for(int i = 1; i <= n; i++) {
            if(ans[i]) cout << ans[i];
        }
        return 0;
    }
    
  • 相关阅读:
    10月27号
    10月23号
    10月26号
    10月30号
    10月28号
    10月29号
    JAVA日报
    JAVA日报
    JAVA日报
    JAVA日报
  • 原文地址:https://www.cnblogs.com/ftae/p/8068248.html
Copyright © 2020-2023  润新知