离线将所有信息存下来,按照字符的大小排序,不难发现,字符ascii越大的最后覆盖最优,那么我们选最大的覆盖,同时并查集维护覆盖过的区间,即让每个节点的父亲都等于它右边的节点,对于每个区间我们跑\([l_i,r_i]\),每次更新\(l\)为\(p[l+1]\),这样遇到覆盖过的区间就直接跳过,那么复杂度为\(O(n+m)\).
#include <bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define ll long long
#define ull unsigned long long
#define PLL pair<ll,ll>
const int N=10000010;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
struct Node{
int l,r;
char c;
}e[N];
int n,m;
char s[N];
int p[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main(){
scanf("%d %d",&n,&m);
getchar();
scanf("%s",s+1);
for(int i=1;i<=m;++i){
scanf("%d %d %c",&e[i].l,&e[i].r,&e[i].c);
}
sort(e+1,e+1+m,[&](Node a,Node b){
return a.c<b.c;
});
for(int i=1;i<=n+1;++i) p[i]=i;
for(int i=m;i>=1;--i){
int l=e[i].l,r=e[i].r;
char c=e[i].c;
while(l<=r){
if(c>s[l]) s[l]=c;
p[l]=l+1;
l=find(p[l+1]);
}
}
ll res=0;
for(int i=1;i<=n;++i) res+=s[i];
printf("%lld\n",res);
return 0;
}