牛客 C. 子段乘积(线段树)

题目链接:点击这里
牛客 C. 子段乘积(线段树)_第1张图片
暴力 O ( n 2 ) O(n^2) O(n2) 超时。

用线段树维护区间乘积的余数,然后查询区间 [ i , i + k − 1 ] [i,i+k-1] [i,i+k1] 即可。其中建树的复杂度是 O ( n ) O(n) O(n),查询的时间复杂度是 O ( l o g n ) O(logn) O(logn)

#include
#include
#include
#include
#include
#include

using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = 200010;

int n, k;
ll a[N];

struct node {
	int l, r;
	ll pd;
}tree[4*N];

inline int lc(int p) {return p<<1;}
inline int rc(int p) {return p<<1|1;}

void build(int i, int l, int r)
{
	tree[i].l = l;
	tree[i].r = r;
	if(l==r)
	{
		tree[i].pd = a[l];
		return ;
	}
	
	int mid = (l + r) >> 1;
	build(lc(i), l, mid);
	build(rc(i), mid+1, r);
	
	tree[i].pd = ( (tree[lc(i)].pd % mod) * (tree[rc(i)].pd % mod) ) % mod;
}

ll query(int i, int ql, int qr)
{
	if(ql<=tree[i].l&&tree[i].r<=qr)
		return tree[i].pd % mod;
		
	int mid = (tree[i].l + tree[i].r) >> 1;
	
	ll res = 1;
	
	if(ql<=mid)
		res *= query(lc(i), ql, qr) % mod;
	if(qr>mid)
		res *= query(rc(i), ql, qr) % mod;
	
	return res % mod;
}

int main()
{
	scanf("%d%d", &n, &k);
	for(int i = 1; i <= n; ++i)
		scanf("%lld", &a[i]);
	
	build(1, 1, n);					//建树
	
	ll ans = -1;
	for(int i = 1; i + k - 1 <= n; ++i)
	{
		ll tmp = query(1, i, i + k - 1); 
		ans = max(ans, tmp);
	}
	
	printf("%lld\n", ans);
	return 0;
}

你可能感兴趣的:(线段树)