#452 Div2 F
题意
给出一个字符串, m 次操作,每次删除区间 ([l,r]) 之间的字符 (c) ,输出最后得到的字符串。
分析
通过树状数组和二分,我们可以把给定的区间对应到在起始字符串上的区间。
然后暴力去删字符即可(因为最多只会删掉等同于字符串长度的字符个数),总共只有 62 种字符,set 维护下位置。
code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4e5 + 10;
int n, m, f[N];
void update(int x) {
for(int i = x; i < N; i += i & -i) f[i]--;
}
int query(int x) {
int s = 0;
for(int i = x; i; i -= i & -i) s += f[i];
return s;
}
int fd(int x) {
int l = 1, r = n, mid;
while(l < r) {
mid = l + r >> 1;
if(query(mid) < x) l = mid + 1;
else r = mid;
}
return l;
}
char s[N];
set<int> S[150];
char ans[N];
int main() {
scanf("%d%d", &n, &m);
scanf("%s", s + 1);
for(int i = 1; i <= n; i++) {
S[s[i]].insert(i);
f[i + (i & -i)] += ++f[i];
}
while(m--) {
char c[2];
int l, r;
scanf("%d%d%s", &l, &r, c);
l = fd(l);
r = fd(r);
auto it = S[c[0]].lower_bound(l);
while(it != S[c[0]].end() && *it <= r) {
update(*it);
auto itt = it;
it++;
S[c[0]].erase(itt);
}
}
for(int i = 0; i < 150; i++) {
for(int j : S[i]) ans[j] = i;
}
for(int i = 1; i <= n; i++) {
if(ans[i]) cout << ans[i];
}
return 0;
}