[codeforces 1311C] Perform the Combo 难懂的表述 逆向前缀和+int溢出

Codeforces Round #624 (Div. 3)   比赛人数6075

[codeforces 1311C] Perform the Combo  难懂的表述 逆向前缀和+int溢出

总目录详见https://blog.csdn.net/mrcrack/article/details/103564004

在线测评地址https://codeforces.com/contest/1311/problem/C

ProblemLangVerdictTimeMemory
C - Perform the Combo GNU C++11Accepted467 ms1600 KB

难懂的表述

I.e. if s="abca", m=2 and p=[1,3] then the sequence of pressed buttons will be 'a' (here you're making a mistake and start performing the combo from the beginning), 'a', 'b', 'c', (here you're making a mistake and start performing the combo from the beginning), 'a' (note that at this point you will not perform the combo because of the mistake), 'b', 'c', 'a'.

上面这段,说得真不好,若是英文为母语的国家,应能表述得更好。一两遍,很难读懂。

Note

The first test case is described in the problem statement. Wrong tries are "a", "abc" and the final try is "abca". The number of times you press 'a' is 4

, 'b' is 2 and 'c' is 2

In the second test case, there are five wrong tries: "co", "codeforc", "cod", "co", "codeforce" and the final try is "codeforces". The number of times you press 'c' is 9

, 'd' is 4, 'e' is 5, 'f' is 3, 'o' is 9, 'r' is 3 and 's' is 1.

借助上面的Note,及难以看懂的那段,来来回回看了两三遍,弄明白。

s="abca", m=2 and p=[1,3]

p[1]=1表示连续打了1个字母a

p[2]=3表示连续打了3个字母abc

别忘了,还有一次正确的,连续打了4个字母abca

首先考虑,枚举[1,m],pi,发现2≤n≤2⋅10^5, 1≤m≤2⋅10^5,1≤pi<n,m*pi=2*10^5*2*10^5=4*10^10超时无疑,马上转换思路,拿出纸笔,得到了

如下该题手工算法

10 5
codeforces
2 8 3 2 9

                12345678910
                codeforces
2               11
8               11111111
3               111 
2               11 
9               111111111
10正确输入       1111111111 
位置上字母数量    6643333331

int溢出如下

aaa...aaa(2*10^5个a)
2*10^5 2*10^5 2*10^5(2*10^5个区间)

字母a的数量2*10^5*2*10^5=4*10^10   int溢出,需采用long long

AC代码如下

#include <cstdio>
#include <cstring>
#define maxn 200010
#define LL long long
using namespace std;
int p,pos[maxn],b[maxn];//pos[i]=j表示区间[1,i]的每个字母数量都需加上j
char s[maxn];
int main(){
	int t,n,m,i;
	LL cnt[30];
	scanf("%d",&t);
	while(t--){
		for(i=0;i<26;i++)cnt[i]=0;
		memset(pos,0,sizeof(pos));
		memset(b,0,sizeof(b));
		scanf("%d%d",&n,&m);
		scanf("%s",s+1);
		for(i=1;i<=m;i++)scanf("%d",&p),pos[p]++;
		pos[n]=1;
		b[n]=pos[n];//b[i]=j表示i位置的字母数量是j
		for(i=n-1;i>=1;i--)b[i]+=b[i+1]+pos[i];//逆向前缀和
		for(i=1;i<=n;i++)cnt[s[i]-'a']+=b[i];//cnt[i]=j表示字母i的数量是j
		for(i=0;i<26;i++)printf("%lld ",cnt[i]);
		printf("\n");			
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值