接着上一篇题解的分析过程,我们还是考虑把操作离线下来看看怎么搞一搞。
注意到我们可以更改排序的 cmp
顺序,原来是从小权值到大权值,这是为了方便进行区间推平。
现在我们换过来,从大权值到小权值,这样做的好处就是保证每个位置至多被修改一次,链表维护一下下一个被修改的位置就好了。
时间复杂度 。
#include<cstdio>
#include<algorithm>
#define int long long
int init(){
char c = getchar();
int x = 0, f = 1;
for (; c < '0' || c > '9'; c = getchar())
if (c == '-') f = -1;
for (; c >= '0' && c <= '9'; c = getchar())
x = (x << 1) + (x << 3) + (c ^ 48);
return x * f;
}
void print(int x){
if (x < 0) x = -x, putchar('-');
if (x > 9) print(x / 10);
putchar(x % 10 + '0');
}
const int N = (int) 1e6 + 5;
struct Node{
int l, r, c;
friend bool operator<(const Node&p, const Node&q){
return p.c > q.c;
}
}s[N];
const int M = (int) 1e7 + 5;
char str[M];
int nxt[M], vis[M];
signed main(){
int n = init(), m = init();
for (int i = 1; i <= n; ++i)
while (str[i] < 33 || str[i] > 126)
str[i] = getchar();
int sLen = 0;
for (int i = 1; i <= m; ++i) {
int l = init(), r = init();
char c = getchar();
while (c < 33 || c > 126)
c = getchar();
s[++sLen] = (Node) {l, r, (int)c};
}
std::stable_sort(s + 1, s + 1 + sLen);
for (int i = 0; i <= n; ++i)
nxt[i] = i + 1, vis[i] = 0;
vis[n + 1] = 0;
int ans = 0;
for (int i = 1; i <= sLen; ++i) {
int l = s[i].l, r = s[i].r, c = s[i].c;
for (int i = l; i <= r;)
if (!vis[i]) {
int j = nxt[i];
vis[i] = c, nxt[i] = nxt[r], ++ans;
i = j;
}
else i = nxt[i];
if (ans == n) break;
}
int sum = 0;
for (int i = 1; i <= n; ++i)
if (vis[i] > (int) str[i]) sum += vis[i];
else sum += (int) str[i];
print(sum), putchar('\n');
}