牛客网暑期多校 (第十场)

链接: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\n", ((query(r, tt+1)-query(l-1, tt+1))%mod+mod)%mod);
            }
        }
    }

    return 0;
}

 

posted @ 2018-08-21 10:54  楼主好菜啊  阅读(271)  评论(0编辑  收藏  举报