题目链接:Codeforces - Letters Removing
每次我们需要从删除之后的序列,找到原来对应的区间。
其实就是一个第k大的问题。平衡树或者权值树维护即可。
然后因为只有删除操作,我们直接从set当中删除即可。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=2e5+10;
int n,m,sum[N<<2]; char str[N],op[3];
set<int> s[200];
void change(int p,int l,int r,int x,int v){
if(l==r){sum[p]+=v; return ;}
int mid=l+r>>1;
if(x<=mid) change(p<<1,l,mid,x,v);
else change(p<<1|1,mid+1,r,x,v);
sum[p]=sum[p<<1]+sum[p<<1|1];
}
int kth(int p,int l,int r,int k){
if(l==r) return l; int mid=l+r>>1;
if(sum[p<<1]>=k) return kth(p<<1,l,mid,k);
else return kth(p<<1|1,mid+1,r,k-sum[p<<1]);
}
void out(int p,int l,int r){
if(!sum[p]) return ;
if(l==r){printf("%c",str[l]); return ;}
int mid=l+r>>1;
out(p<<1,l,mid),out(p<<1|1,mid+1,r);
}
signed main(){
cin>>n>>m; scanf("%s",str+1);
for(int i=1;i<=n;i++) s[str[i]].insert(i),change(1,1,n,i,1);
for(int i=1,l,r;i<=m;i++){
scanf("%d %d %s",&l,&r,op);
int ql=kth(1,1,n,l),qr=kth(1,1,n,r);
auto itl=s[op[0]].lower_bound(ql),itr=s[op[0]].upper_bound(qr);
for(auto j=itl;j!=itr;j++) change(1,1,n,*j,-1);
s[op[0]].erase(itl,itr);
}
out(1,1,n);
return 0;
}