因为每个字符只会删除一次,因此删除的复杂度单点是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; }