题目描述
亚可喜欢上了收集不包括空格的可见字符(ASCII码为33~126),在她眼中,一个字符的价值为其ASCII码大小,比如’a’的价值为97。
目前她已经收集了n个不包括空格的可见字符,第i个字符S[i]。可是她想要把自己收集的nn个字符的价值和最大化,因此去请求了戴安娜的帮助。戴安娜有m种魔法,第i种魔法可以将[l[i],r[i]]区间的一个字符替换为c[i]。因为戴安娜出色的魔力,所以每种魔法都可以使用无限次。
请问戴安娜使用完若干次魔法后,亚可收集的n个字符的最大价值和可以是多少?
输入样例
3 3
aaa
1 3 b
2 3 c
3 3 d
输出样例
297
算法
(并查集)
其实这一题与 牛客练习赛91_D 的第二种方法基本上相同,AcWing题解戳这里,牛客题解戳这里 在这里我们使用并查集来记录每个点的"后一个应该被访问的点是哪个",因为我们在这里与easy版本一样是根据c[i]进行了排序,那么我就保证了每个点只会被修改一次 并查集操作
for(int i=1;i<N;i++) f[i]=i;//用f[i]来记录下一个要更改的点
for(int i=0;i<m;i++)
{
int l=e[i].l,r=e[i].r,c=e[i].c;;
while(l<=r)
{
st[l]=max(st[l],(char)e[i].c);
f[l]=l+1;//下一个
l=find(f[l]);
}
}
这题真的太容易超时了,加上牛客的测评机也不是很稳定所以我用了快读和快输出
C++ 代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e7+10;
int f[N],n,m;
char st[N];
typedef long long ll;
struct node
{
int l,r,c;
bool operator<(const node &w)const
{
return c>w.c;
}
}e[N];
void print(ll x)
{
int num = 0; char c[15];
while(x) c[++num] = (x%10)+48, x /= 10;
while(num) putchar(c[num--]);
putchar('\n');
}
void get(int &x)
{
char c = getchar(); x = 0;
while(c < '0' || c > '9') c = getchar();
while(c <= '9' && c >= '0') x = x*10+c-48, c = getchar();
}
int find(int x)
{
if(x!=f[x])
f[x]=find(f[x]);
return f[x];
}
int main()
{
cin>>n>>m;
getchar();
for(int i=1;i<=n;i++)
{
char t;
t=getchar();
st[i]=t;
}
for(int i=0;i<m;i++)
{
get(e[i].l);
get(e[i].r);
char t;
t=getchar();
e[i].c=(int)t;
}
sort(e,e+m);
for(int i=1;i<N;i++) f[i]=i;//用f[i]来记录下一个要更改的点
for(int i=0;i<m;i++)
{
int l=e[i].l,r=e[i].r,c=e[i].c;;
while(l<=r)
{
st[l]=max(st[l],(char)e[i].c);
f[l]=l+1;//下一个
l=find(f[l]);
}
}
ll sum=0;
for(int i=1;i<=n;i++) sum+=(int)st[i];
print(sum);
}