Official

F - Two Sequence Queries Editorial by en_translator


Consider solving this problem using a lazy segment tree.
For details on lazy segment trees, please refer to other editorials and the explanation of AtCoder Library.

Specifically, for each segment \(a\cdot2^k+1\leq i\leq (a+1)2^k\) for integers \(a,k\geq 0\) and \(2^k(a+1)\leq N\), we want to manage the sum of \(A_i\times B_i\) within the segment, and apply addition to \(A_i\) and \(B_i\) fast enough (basically, in \(O(1)\) time).

The set of actions we consider consists of “adding \(x\) to each element of \(A\) and \(y\) to that of \(B\) (within the segment)” for all integers \(x\) and \(y\). These include operations given by queries and closed under composition. Also, \(x=y=0\) yields the identity element when the set of actions are considered as a set of maps.

For an aforementioned segment \(a\cdot2^k+1\leq i\leq (a+1)2^k\) (where we denote \(L=a\cdot2^k+1\) and \(R=(a+1)2^k\)), it is insufficient to store the values \(\displaystyle\sum_{i=L}^R (A_i\times B_i)\) for each segment so as to update \(\displaystyle\sum_{i=L}^R (A_i\times B_i)\), the sum of \(A_i\times B_i\).
This is because:

\[ \displaystyle\sum_{i=L}^R ((A_i+x)\times (B_i+y)) =\displaystyle\sum_{i=L}^R (A_i\times B_i) +y\displaystyle\sum_{i=L}^R A_i +x\displaystyle\sum_{i=L}^R B_i +(R-L+1)xy, \]

which means, given only the information on the segment \(\displaystyle\sum_{i=L}^R (A_i\times B_i)\) and on the map \(x\) and \(y\), the value resulting from the update is not uniquely determined.

Instead, consider managing the length \((R-L+1)\), and three kinds of sum, \(\displaystyle\sum_{i=L}^R A_i\), \(\displaystyle\sum_{i=L}^R B_i\), and \(\displaystyle\sum_{i=L}^R (A_i\times B_i)\), for each segment. Then, one can update the value \(\displaystyle\sum_{i=L}^R (A_i\times B_i)\) according to the equation above in \(O(1)\) time. Also,

\[ \displaystyle\sum_{i=L}^R (A_i+x) =\displaystyle\sum_{i=L}^R A_i+(R-L+1)x, \\ \displaystyle\sum_{i=L}^R (B_i+y) =\displaystyle\sum_{i=L}^R B_i+(R-L+1)y, \]

which enables to update these values in response to an action in \(O(1)\) time as well. The length of segment is invariant by an action. In order that concatenation of segments and update operations commute, we can take the sum of the lengths and sums of the two. A segment of length \(0\) with the three sums all being \(0\) acts as the identity element with respect to concatenation.

Therefore, the lazy segment tree enables to find the answer. The complexity is \(O(Q\log N)\), which is fast enough.
Hence, the problem has been solved.

Be sure to print the answer modulo \(998244353\).

#include <bits/stdc++.h>
#include <atcoder/lazysegtree>
#include <atcoder/modint>

using namespace std;
using namespace atcoder;

using mint = modint998244353;


struct S {
    mint len,Asum,Bsum,ABsum;
};
struct F {
    mint Aadd,Badd;
};

S op(S l, S r) {
    return S{
        l.len + r.len,
        l.Asum + r.Asum,
        l.Bsum + r.Bsum,
		l.ABsum + r.ABsum,
    };
}
S e() { return S{mint(0),mint(0),mint(0),mint(0)}; }
S mapping(F op, S tgt) {
    return S{
		tgt.len,
		tgt.Asum+(op.Aadd*tgt.len),
		tgt.Bsum+(op.Badd*tgt.len),
		tgt.ABsum+(op.Aadd*tgt.Bsum)+(op.Badd*tgt.Asum)+(op.Aadd*op.Badd*tgt.len)
	};
}
F composition(F l, F r) { return F{l.Aadd+r.Aadd,l.Badd+r.Badd}; }
F id() { return F{mint(0),mint(0)}; }

int main() {
	int n,q;
	int t,l,r,x;

	cin>>n>>q;
	vector<int>a(n),b(n);
	vector<S>tmp(n);

	for(int i=0;i<n;i++)cin>>a[i];
	for(int i=0;i<n;i++)cin>>b[i];
	for(int i=0;i<n;i++)tmp[i]=S{mint(1),mint(a[i]),mint(b[i]),mint(a[i])*mint(b[i])};
	lazy_segtree<S, op, e, F, mapping, composition, id> seg(tmp);

	for(int i=0;i<q;i++){
		cin>>t>>l>>r;
		if(t<3)cin>>x;
		if(t==1)seg.apply(l-1,r,F{mint(x),mint(0)});
		if(t==2)seg.apply(l-1,r,F{mint(0),mint(x)});
		if(t==3)cout<<(seg.prod(l-1,r).ABsum.val())<<endl;
	}	
	return 0;
}

posted:
last update: