2021牛客暑期多校训练营5-C题

C题:Cheating and Stealing

原题

题目大意

2021牛客暑期多校训练营5-C题

solution

乍一看题目非常简单,枚举 i : 1 → n i :1\to n i:1→n,然后把整个字符串扫一遍求出所有 f i ( S ) f_i(S) fi​(S)。但这样的时间复杂度是 O ( n 2 ) O(n^2) O(n2)。而题目的测试数据范围是 1 ≤ n ≤ 1 0 6 1\leq n\leq 10^6 1≤n≤106,显然不允许。需要换个思路。
根据题意Gromah想要在分数上限为 i i i时获胜。
则需满足 得 分 的 次 数 ≥ i , 并 且 得 分 次 数 − 失 分 次 数 ( 即 对 方 得 分 ) ≥ 2 得分的次数\geq i ,并且得分次数-失分次数(即对方得分)\geq 2 得分的次数≥i,并且得分次数−失分次数(即对方得分)≥2
对于得分,使用前缀和可以解决这个问题。某一区间[x,y]内的得分为W[y]-W[x]
再开一个数组储存在一个区间内的得失分的差值。从而实现 O ( 1 ) O(1) O(1)的询问时间复杂度。总共的局数 = n i ( i 为 ) =\large\frac{n}{i}(\small i为) =in​(i为)呈现调和级数的形式。就能做到把时间复杂度降到 O ( n   l o g   n ) O(n\ log\ n) O(n log n)

c o d e \large code code

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+7,mod=998244353;
char s[N];
int n,L[N],W[N],d[N],pL[N],pW[N],f1[N],f2[N];
void pre()
{
	int k;
	for(int i=n;i>=1;i--){
		k=i+1;
		while(k<=n&&d[k]<=d[i]) k=f1[k];//f1[i]表示i点后Gromah得分的最近的点下标
		f1[i]=k;
		k=i+1;
		while(k<=n&&d[k]>=d[i]) k=f2[k];//f1[i]表示i点后Gromah失分的最近的点下标
		f2[i]=k;
	}
	
}
void solved()
{
	ll ans=0,p=1;
	for(int i=1;i<=n;i++)
	{
		int endit=1e9+7,x=1;
		ll sum=0;
		while(W[n]-W[x-1]>=i||L[n]-L[x-1]>=i)
		{
			endit=1e9+7;//endit是该局比赛结束(有一人已经获胜)的末尾下标
			if(W[n]-W[x-1]>=i) endit=min(endit,pW[W[x-1]+i]);
			if(L[n]-L[x-1]>=i) endit=min(endit,pL[L[x-1]+i]);
			if(abs(d[endit]-d[x-1])<2){//还不存在两分的分差,继续向后
				int o1=endit,o2=endit;
				while(o1<=n&&d[o1]-d[x-1]<2){
					o1=f1[o1];
				}
				while(o2<=n&&d[o2]-d[x-1]>-2){
					o2=f2[o2];
				}
				endit=min(o1,o2);//更新末尾下标
				if(endit>n) break;//全部遍历完成,跳出循环
			}
			if(d[endit]-d[x-1]>0)//Gromah这一局获得胜利
			sum++;
			x=endit+1;//开始下一局
		}
		ans=ans+sum*p%mod;//计算结果
		p=p*(1+n)%mod;
	}
	cout<<ans<<"\n";
}
int main()
{
	cin>>n>>(s+1);
	for(int i=1;i<=n;i++){
		L[i]+=L[i-1];//统计前缀和,到i点为止已经有多少个L或W 
		W[i]+=W[i-1];
		if(s[i]=='L'){
			L[i]++;
			pL[L[i]]=i;//记录各个为L的点的下标 
		}
		if(s[i]=='W'){
			W[i]++;
			pW[W[i]]=i;//记录各个为W的点的下标 
		}
		d[i]=W[i]-L[i];
	}
	pre();
	solved();
	return 0;
}
上一篇:gcc -O2 优化,到底做了什么? 程序都不能正常运行了。


下一篇:softmax回归理论