列表

详情


NC231634. 小哈的魔法咒语

描述

魔法学院 CCNU 的新晋魔法师小哈正在练习课上学到的咒语。为了通过魔法学院的考试,小哈必须在一定时间内念完所有的咒语。
形式化的说,咒语可以认为是一个长度为 n 的字符串,记 为字符串 sij 的子串。小哈在魔法考试中需要在 n 秒内每秒念一个咒语,念完字符串 s 的每一个前缀串

小哈念每个前缀串咒语 需要花费 v_i 的法力值,但由于这场考试是 CF 赛制(随着时间的流逝念咒语消耗的法力值会成倍变大),第 k 秒念第 i 条咒语需要花费的法力值为

考试的主考官 先生还告诉小哈:对于,如果, 这条咒语要在 前被念完。形式化的讲: 如果记 这条咒语被念的时间为第 t_i 秒,小哈必须保证

小哈想知道他要通过考试的最小法力值消耗是多少。

输入描述

第一行输入一个整数, n 表示咒语字符串的长度。 

第二行输入长为 n 的字符串表示咒语, 由小写字母组成。

第三行为 n 个整数,第 i 个整数代表念完第 i 个咒语所需法力值 v_i (

输出描述

输出一个整数表示小哈通过考试的最小法力值消耗。

示例1

输入:

2 
ac
1 2

输出:

4

示例2

输入:

5 
aacaa
1 2 3 4 5

输出:

50

说明:

对于样例1:没有额外限制,小哈先念s[1, 2],再念 s[1,1]。所需法力值为 2 * 1 + 1 * 2 = 4,可以证明 4 是小哈消耗的最小法力值。

对于样例2:有如下限制

s[1,1] 需要在 s[1,2] 前被念

s[1,1] 需要在 s[1,4] 前被念

s[1,1] 需要在 s[1,5] 前被念

s[1,2] 需要在 s[1,5] 前被念

小哈按如下顺序念:
s[1,3],s[1,1],s[1,4],s[1,2],s[1,5],消耗法力为3 * 1 + 1 * 2 + 4 * 3 + 2 * 4 + 5 * 5 = 50
,可以证明 50 是小哈消耗的最小法力值。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 63ms, 内存消耗: 6996K, 提交时间: 2021-12-12 14:28:03

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

const int N = 100010;

int v[N];
int nxt[N], fa[N], siz[N];
vector<int> edge[N];

struct node
{
	int x,siz;
	long long w;
	bool operator<(const node b)const{return w*b.siz<b.w*siz;}
};

priority_queue<node> q;
long long ans;

int find(int x)
{
	return fa[x] == x ? x : fa[x] = find(fa[x]);
}

void push(int x)
{
	q.push(node{x,siz[x],v[x]});
}

void merge(int f,int x)
{
	ans+=1ll*siz[f]*v[x];
//	cout<<"merge "<<f<<" "<<x<<" "<<ans<<endl;
	v[f]+=v[x];
	siz[f]+=siz[x];
}

int main()
{
	int n;
	string s;
	int i, j;
	int x, f;
	
	cin >> n;
	cin >> s;
	for(i = 1; i <= n; i ++)
		cin >> v[i];
	
	j=nxt[0]=-1;
	i=0;
	while(i<n){
		while(-1!=j && s[i]!=s[j])j=nxt[j];
		nxt[++i]=++j;
	}
	
//	for(i=1;i<=n;i++)cout<<nxt[i]<<' ';cout<<endl;
	
	for(i = 1, ans = 0; i <= n; i ++)
	{
		fa[i] = i;
		siz[i] = 1;
		ans += v[i];
		push(i);
	}
	
//	cout<<ans<<endl;

	while(!q.empty())
	{
		x=q.top().x;
//		cout<<x<<endl;
		q.pop();
		if(x!=find(x))continue;
		x=find(x);
		fa[x]=f=find(nxt[x]);
		merge(f,x);
		if(f)push(f);
	}
    
    cout << ans << endl;
	
	return 0;
}

上一题