CF899F Letters Removing(树状数组+二分)

因为每个字符只会删除一次,因此删除的复杂度单点是O(1),对总复杂度没有影响

主要是考虑我们每次的l,r都是会根据之前删除的变化的,因此如果想知道真实的位置

其实可以使用树状数组+二分求取,对于删除,我们可以对每个字符维护一个set,这样就能够成功删除

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int n,m;
int tr[N];
vector<int> tmp;
int lowbit(int x){
    return x&-x;
}
void add(int x,int c){
    int i;
    for(i=x;i<N;i+=lowbit(i)){
        tr[i]+=c;
    }
}
int sum(int x){
    ll res=0;
    int i;
    for(i=x;i;i-=lowbit(i)){
        res+=tr[i];
    }
    return res;
}
set<int> st[N];
int vis[N];
map<char,int> mp;
int get(int x){
    int l=1,r=n;
    while(l<r){
        int mid=l+r>>1;
        if(sum(mid)>=x)
            r=mid;
        else
            l=mid+1;
    }
    return l;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    string s;
    cin>>s;
    int cnt=0;
    s=" "+s;
    int i;
    for(i=0;i<9;i++){
        char sign='0'+i;
        mp[sign]=++cnt;
    }
    for(i=0;i<26;i++){
        char sign='a'+i;
        mp[sign]=++cnt;
    }
    for(i=0;i<26;i++){
        char sign='A'+i;
        mp[sign]=++cnt;
    }
    for(i=1;i<=n;i++){
        int pos=mp[s[i]];
        add(i,1);
        st[pos].insert(i);
    }
    for(i=1;i<=m;i++){
        int l,r;
        char c;
        cin>>l>>r>>c;
        int pos1=get(l);
        int pos2=get(r);
        tmp.clear();
        auto it=st[mp[c]].lower_bound(pos1);
        while(it!=st[mp[c]].end()&&*it<=pos2){
            vis[*it]=1;
            add(*it,-1);
            tmp.push_back(*it);
            it++;
        }
        for(auto x:tmp){
            st[mp[c]].erase(x);
        }
    }
    for(i=1;i<=n;i++){
        if(!vis[i]){
            cout<<s[i];
        }
    }
    cout<<endl;
}

 

posted @ 2020-09-24 22:01  朝暮不思  阅读(177)  评论(0)    收藏  举报