2021牛客暑期多校训练营5 C. Cheating and Stealing(模拟,思维)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营5 C. Cheating and Stealing(模拟,思维)相关的知识,希望对你有一定的参考价值。

LINK

当胜负点定为 k k k时候,最多存在 ∣ S ∣ k \\frac{|S|}{k} kS局游戏

如果我们能 O ( 1 ) O(1) O(1)求出每一局,总体复杂度就是 O ( ∣ S ∣ l o g ( ∣ S ∣ ) ) O(|S|log(|S|)) O(Slog(S))

考虑本局游戏在点 i i i开始,胜负点为 k k k

考虑记录一个 A A A z z z局游戏的局面在 p o s a [ z ] posa[z] posa[z]位置, B B B p o s b [ z ] posb[z] posb[z]位置

容易知道 A A A a p = p o s a [ p r e a i − 1 + k ] ap=posa[prea_{i-1}+k] ap=posa[preai1+k]位置首次达到胜负点, B B B b p = p o s b [ p r e b i − 1 + k ] bp=posb[preb_{i-1}+k] bp=posb[prebi1+k]

考虑 a p < b p ap<bp ap<bp

A A A已经比 B B B多赢两局,直接结束比赛

A A A只比 B B B多赢一局,只需要看一下 a p + 1 ap+1 ap+1位置是谁赢

如果是 A A A赢,显然游戏结束.如果是 B B B赢,现在双方平局

考虑预处理一个 t i e [ i ] tie[i] tie[i]表示从 i i i开始平局,需要在哪一个位置终结比赛

这样就可以 O ( 1 ) O(1) O(1)判断

t i e tie tie数组的转移如下

t i e [ i ] = ( a i + 1 = = a i + 2 ? i + 2 : t i e [ i + 2 ] ) tie[i]=(a_{i+1}==a_{i+2}?i+2:tie[i+2]) tie[i]=(ai+1==ai+2?i+2:tie[i+2])

#include<iostream>
#include <assert.h>
using namespace std;
const int maxn = 2e6+10;
const int mod = 998244353;
int n,pa[maxn],pb[maxn],posa[maxn],posb[maxn],tie[maxn],f[maxn];
char a[maxn];
int get(int x,int k)//胜负点为k球 
{
	int nxta = posa[pa[x-1]+k], nxtb = posb[pb[x-1]+k];
	if( nxta==0 && nxtb==0 )	return n+1;//赢不了
	if( nxta && ( !nxtb || nxta<nxtb ) )
	{
		if( pb[nxta]-pb[x-1]<=k-2 ) return nxta;
		if( a[nxta+1]=='L' )	return nxta+1;
		if( tie[nxta+1]<1 || tie[nxta+1]>n )	return n+1;
		if( a[tie[nxta+1]]=='W' )	f[k]++;
		return tie[nxta+1];	
	}
	if( nxtb && ( !nxta || nxtb<nxta ) )
	{
		if( pa[nxtb]-pa[x-1]<=k-2 ) { f[k]++; return nxtb; }
		if( a[nxtb+1]=='W' )	{ f[k]++; return nxtb+1; }
		if( tie[nxtb+1]<1 || tie[nxtb+1]>n )	return n+1;
		if( a[tie[nxtb+1]]=='W' )	f[k]++;
		return tie[nxtb+1];
	}	
}
int main()
{
	cin >> n >> (a+1);
	for(int i=1;i<=n;i++)
	{
		pa[i] = pa[i-1]+( a[i]=='L' );
		pb[i] = pb[i-1]+( a[i]=='W' );
		if( a[i]=='L' )	posa[pa[i]] = i;
		if( a[i]=='W' )	posb[pb[i]] = i;
	}
	for(int i=n;i>=1;i--)
		tie[i] = a[i+1]==a[i+2]?i+2:tie[i+2];
	int ans = 0, base = 1;
	for(int i=1;i<=n;i++)
	{
		int j = 1;
		while( j<=n )	j = get(j,i)+1;
		ans = ( ans+1ll*f[i]*base%mod )%mod;
		base = 1ll*base*(n+1)%mod;
	}
	cout << ans;
	return 0;
}

以上是关于2021牛客暑期多校训练营5 C. Cheating and Stealing(模拟,思维)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营5,签到题BDHJK

2021牛客暑期多校训练营2

2021牛客暑期多校训练营4

2021牛客暑期多校训练营9

2021牛客暑期多校训练营3

2021牛客暑期多校训练营8,签到题ADEK