Description
Petya has a string of length n consisting of small and large English letters and digits.
He performs m operations. Each operation is described with two integers l and r and a character c: Petya removes from the string all characters c on positions between l and r, inclusive. It's obvious that the length of the string remains the same or decreases after each operation.
Find how the string will look like after Petya performs all m operations.
solution
正解:线段树+set
我们先要将([l,r])还原的原字符串上,([l,r])对应着原序列的第 (l,r) 个不是空位的位置,线段树维护即可
对于删除,我们直接对每一个元素开一个set,找出区间后直接暴力删除即可,因为每一个元素只会被删一次,复杂度是 (O(n*logn)).
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#define RG register
#define iter iterator
#define ls (o<<1)
#define rs (o<<1|1)
using namespace std;
typedef long long ll;
const int N=200005;
int n,m,tr[N<<2],T=141;char s[N];
inline void build(int l,int r,int o){
if(l==r){tr[o]=1;return ;}
int mid=(l+r)>>1;
build(l,mid,ls);build(mid+1,r,rs);
tr[o]=tr[ls]+tr[rs];
}
set<int>S[142];
set<int>::iter it;
inline int qry(int l,int r,int o,int k){
if(l==r)return l;
int mid=(l+r)>>1,sum=tr[ls];
if(sum>=k)return qry(l,mid,ls,k);
return qry(mid+1,r,rs,k-sum);
}
inline void ins(int l,int r,int o,int sa){
tr[o]--;if(l==r)return ;
int mid=(l+r)>>1;
if(sa<=mid)ins(l,mid,ls,sa);
else ins(mid+1,r,rs,sa);
}
int st[N],top=0;bool d[N];
void work()
{
scanf("%d%d",&n,&m);
scanf("%s",s+1);
build(1,n,1);
for(int i=1;i<=n;i++)S[(int)s[i]].insert(i);
int l,r,c;char ch[2];
while(m--){
scanf("%d%d%s",&l,&r,ch);c=ch[0];
l=qry(1,n,1,l);r=qry(1,n,1,r);
it=S[c].lower_bound(l);
while(it!=S[c].end() && *it<=r)st[++top]=*it,++it;
while(top){
ins(1,n,1,st[top]);
S[c].erase(st[top]);
d[st[top--]]=1;
}
}
for(int i=1;i<=n;i++)if(!d[i])putchar(s[i]);
}
int main()
{
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
work();
return 0;
}