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 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8059768.html