[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

Problem Lang Verdict Time Memory
C - Perform the Combo GNU C++11 Accepted 467 ms 1600 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;
}
发布了552 篇原创文章 · 获赞 531 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/mrcrack/article/details/104491353