链接:https://www.nowcoder.com/acm/contest/148/D
来源:牛客网
题目描述
Prefix Sum is a useful trick in data structure problems.
For example, given an array A of length n and m queries. Each query gives an interval [l,r] and you need to calculate . How to solve this problem in O(n+m)? We can calculate the prefix sum array B in which Bi is equal to . And for each query, the answer is Br-Bl-1.
Since Rikka is interested in this powerful trick, she sets a simple task about Prefix Sum for you:
Given two integers n,m, Rikka constructs an array A of length n which is initialized by Ai = 0. And then she makes m operations on it.
There are three types of operations:
1. 1 L R w, for each index i ∈ [L,R], change Ai to Ai + w.
2. 2, change A to its prefix sum array. i.e., let A' be a back-up of A, for each i ∈ [1,n], change Ai to .
3. 3 L R, query for the interval sum .
输入描述:
The first line contains a single number t(1≤ t ≤ 3), the number of the testcases.
For each testcase, the first line contains two integers n,m(1 ≤ n,m ≤ 105).
And then m lines follow, each line describes an operation(1 ≤ L ≤ R≤ n, 0 ≤ w ≤ 109).
The input guarantees that for each testcase, there are at most 500 operations of type 3.
输出描述:
For each query, output a single line with a single integer, the answer modulo 998244353.
示例1
输入
1
100000 7
1 1 3 1
2
3 2333 6666
2
3 2333 6666
2
3 2333 6666
输出
13002
58489497
12043005
题意 : 给你一个长度为 n 的序列,初始元素均为 0 , 有 3 种操作, 1 是给序列的某一个区间加上同一个元素, 2 是将此序列变为它的前缀和序列, 3 是求序列某一个区间的和 ,数据保证 操作3 的次数不多于 500 次
思路分析 : 这题想了好久才勉强有点思路,挺不错的一道题目 , 可以这样想,当我们在某一个位置上增加一个数时,再求上几次前缀和,画个表写出来,会发现这其实就是一个斜着的杨辉三角,找到其是哪一行哪一列,直接公式就可以算出来, C(n-1,m-1)。操作 2 的话就累加,操作3的话就进行一次求和计算即可。
代码示例 :
#include <bits/stdc++.h> using namespace std; #define ll long long const ll maxn = 2e5+5; const ll mod = 998244353; ll n, m; struct node{ ll tt, pos, w; }a[maxn]; ll cnt; ll pp[maxn], inv[maxn]; ll qw(ll x, ll n){ ll res = 1; while(n > 0){ if (n & 1) res = res * x % mod; x = x * x % mod; n >>= 1; } return res%mod; } void init() { pp[0] = 1; for(ll i = 1; i <= 200000; i++) { pp[i] = (pp[i-1]*i)%mod; inv[i] = qw(pp[i], mod-2); } inv[0] = inv[1]; } ll C(ll n, ll m){ ll ans = pp[n]*inv[m]%mod*inv[n-m]%mod; return ans%mod; } ll query(ll pos, ll tt){ ll ans = 0; for(ll i = 0; i < cnt; i++){ if (a[i].pos <= pos) { ans += a[i].w*C(pos-a[i].pos+tt-a[i].tt-1, tt-a[i].tt-1)%mod; ans %= mod; } } return ans; } int main () { ll t; ll pt, l, r, w; init(); cin >> t; while(t--){ cin >> n >> m; cnt = 0; ll tt = 1; while(m--){ scanf("%lld", &pt); if (pt == 1){ scanf("%lld%lld%lld", &l, &r, &w); a[cnt].tt = tt-1, a[cnt].pos = l, a[cnt].w = w%mod; cnt++; a[cnt].tt = tt-1, a[cnt].pos = r+1, a[cnt].w = -w%mod; cnt++; } else if (pt == 2) tt++; else { scanf("%lld%lld", &l, &r); printf("%lld ", ((query(r, tt+1)-query(l-1, tt+1))%mod+mod)%mod); } } } return 0; }