CF899F. Letters Removing
给一个字符串支持以下操作:区间删除某个特定字符。最后输出字符串。n,m<=200000。
这题我居然不会可以回家了。。
首先,单点删除,选个平衡树比如set。
然后,他给的下标是会随删除操作变化的,需要查“存在于字符串中的第K个是谁”来找左右端点,一个树状数组搞定。
树状数组找出题目给的x,y在初始串中的下标L,R,对每个字符开一个set存它的所有出现位置,把这个set里在L,R间的位置去掉,去掉的同时把树状数组里的对应位置-1,即可。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<stdlib.h> 5 #include<set> 6 #include<math.h> 7 //#include<iostream> 8 using namespace std; 9 10 int n,m; 11 #define maxn 200011 12 char a[maxn]; 13 set<int> s[233]; 14 #define IT set<int>::iterator 15 struct BIT 16 { 17 int a[maxn]; 18 BIT() {memset(a,0,sizeof(a));} 19 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 20 int query(int x) {int ans=0;for (;x;x-=x&-x) ans+=a[x];return ans;} 21 int find(int x) 22 { 23 int now=0,tot=0; 24 for (int j=20;j>=0;j--) 25 { 26 now+=1<<j; 27 if (now<=n && a[now]+tot<x) tot+=a[now]; 28 else now-=1<<j; 29 } 30 return now+1; 31 } 32 }t; 33 int main() 34 { 35 scanf("%d%d",&n,&m); 36 scanf("%s",a+1); 37 for (int i=1;i<=n;i++) s[a[i]].insert(i); 38 for (int i=1;i<=n;i++) t.a[i]=i&-i; 39 40 int x,y;char id[5]; 41 while (m--) 42 { 43 scanf("%d%d%s",&x,&y,id); 44 int L=t.find(x),R=t.find(y); 45 IT it=s[id[0]].lower_bound(L); 46 for (;it!=s[id[0]].end() && *it<=R;) 47 { 48 IT tmp=it; it++; 49 t.add(*tmp,-1); 50 s[id[0]].erase(tmp); 51 } 52 } 53 for (int i=1;i<=n;i++) if (t.query(i)-t.query(i-1)) putchar(a[i]); 54 return 0; 55 }