zoukankan      html  css  js  c++  java
  • 牛客网暑期多校 (第十场)

    链接: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;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    关于MFC消息的总结
    关于VS中包含库、附加包含库、
    关于MFC中重载函数是否调用基类相对应函数的问题
    关于子窗口处理自身消息而不扩散给父窗口的问题
    进程与线程理解-1
    程序设计思想-2
    线程与进程
    网路编程之socket与 socketserver、黏包
    网络编程之TCP协议与UDP协议
    网络编程基础
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9510096.html
Copyright © 2011-2022 走看看