题目:
分析:
题目中所要求的长度为k的连续子段的乘积对998244353取模余数的最大值,那么我们可以用线段树来存取区间的乘积,线段树的叶子节点存取对应下标的值,根节点存取左右子树的乘积,以此种方式建完树后,再遍历 [1,n-k+1] 每次取其中的最大值。
#include <iostream>
#include <cstdio>
#include <cstring>
#define ll long long
using namespace std;
const int MAXN = 200005;
const long long mod = 998244353;
int n,k;
long long num[MAXN],ans;
struct Tree
{
ll l,r,pro;
}tree[4*MAXN];
void Build(int l,int r,int i)
{
tree[i].l = l;tree[i].r = r;
if(l==r)
{
tree[i].pro = num[l];
return;
}
int mid = (l + r) >> 1;
Build(l,mid,2*i);
Build(mid+1,r,2*i+1);
tree[i].pro = ((tree[2*i].pro % mod) * (tree[2*i+1].pro % mod)) % mod;
}
ll Query(int i,int l,int r)
{
if(tree[i].l>=l && tree[i].r<=r) return tree[i].pro % mod;
int mid = (tree[i].l + tree[i].r) >> 1;
ll tmpL=1,tmpR=1;
if(tree[2*i].r >= l)
tmpL = Query(2*i,l,r) % mod;
if(tree[2*i+1].l <= r)
tmpR = Query(2*i+1,l,r) % mod;
return (tmpL * tmpR) % mod;
}
int main()
{
ll tmp;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)
scanf("%lld",&num[i]);
Build(1,n,1);
for(int i=1;i+k-1<=n;++i)
{
tmp = Query(1,i,i+k-1);
ans = max(ans,tmp);
}
printf("%lld\n",ans);
return 0;
}