codeforce452DIV2——F. Letters Removing
题意:
给一个字符串和m个操作,每次给出l,r,c,把字符串中l-r这段区间的字符为c的字符删掉,求最后的字符串。(n,m<=2e5)
线段树。注意这个区间修改和普通区间修改的区别。
他们都是用树状数组做的哎,可是我对树状数组一直是一脸懵逼
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 using namespace std; 6 const int maxn=200000+100; 7 const int maxnode=65; 8 int n,m; 9 char s[maxn]; 10 int a[maxn]; 11 int get(char c){ 12 if(c>='A'&&c<='Z')return c-'A'; 13 if(c>='a'&&c<='z')return c-'a'+26; 14 if(c>='0'&&c<='9')return c-'0'+52; 15 } 16 char res(int x){ 17 if(x>=0&&x<26)return x+'A'; 18 if(x>=26&&x<52)return x-26+'a'; 19 if(x>=52&&x<62)return x-52+'0'; 20 } 21 int sumv[4*maxn],num[4*maxn][maxnode]; 22 void build(int o,int L,int R){ 23 if(L==R){ 24 sumv[o]=1; 25 num[o][a[L]]=1; 26 return ; 27 } 28 int M=L+(R-L)/2; 29 build(2*o,L,M); 30 build(2*o+1,M+1,R); 31 sumv[o]=sumv[2*o]+sumv[2*o+1]; 32 for(int i=0;i<62;i++) 33 num[o][i]=num[2*o][i]+num[2*o+1][i]; 34 } 35 int ql,qr,c; 36 void update(int o,int L,int R){ 37 if(num[o][c]==0)return ; 38 if(ql>R||qr<L) 39 return ; 40 if(L==R){ 41 if(num[o][c]){ 42 sumv[o]=0; 43 num[o][c]=0; 44 } 45 return ; 46 } 47 int M=L+(R-L)/2; 48 update(2*o,L,M); 49 update(2*o+1,M+1,R); 50 sumv[o]=sumv[2*o]+sumv[2*o+1]; 51 num[o][c]=num[2*o][c]+num[2*o+1][c]; 52 } 53 int find(int o,int L,int R ,int k){ 54 int M=L+(R-L)/2; 55 if(L==R)return L; 56 if(sumv[2*o]>=k)return find(2*o,L,M,k); 57 else return find(2*o+1,M+1,R,k-sumv[2*o]); 58 } 59 void tra(int o,int L,int R){ 60 if(sumv[o]==0)return ; 61 if(L==R){ 62 for(int i=0;i<62;i++) 63 if(num[o][i]){ 64 int c=res(i); 65 printf("%c",c); 66 } 67 return ; 68 } 69 int M=L+(R-L)/2; 70 tra(2*o,L,M); 71 tra(2*o+1,M+1,R); 72 } 73 int main(){ 74 scanf("%d%d",&n,&m); 75 scanf("%s",s+1); 76 for(int i=1;i<=n;i++)a[i]=get(s[i]); 77 build(1,1,n); 78 int L,R; 79 char cc; 80 for(int i=1;i<=m;i++){ 81 scanf("%d%d %c",&L,&R,&cc); 82 L=find(1,1,n,L),R=find(1,1,n,R); 83 ql=L,qr=R,c=get(cc); 84 update(1,1,n); 85 } 86 tra(1,1,n); 87 return 0; 88 }