2021牛客暑期多校训练营5 C. Cheating and Stealing(模拟,思维)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营5 C. Cheating and Stealing(模拟,思维)相关的知识,希望对你有一定的参考价值。
当胜负点定为 k k k时候,最多存在 ∣ S ∣ k \\frac{|S|}{k} k∣S∣局游戏
如果我们能 O ( 1 ) O(1) O(1)求出每一局,总体复杂度就是 O ( ∣ S ∣ l o g ( ∣ S ∣ ) ) O(|S|log(|S|)) O(∣S∣log(∣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[preai−1+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[prebi−1+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(模拟,思维)的主要内容,如果未能解决你的问题,请参考以下文章