列表

详情


NC226172. 智乃酱的平方数列

描述

想必你一定会用线段树维护等差数列吧?让我们来看看它的升级版。

请你维护一个长度为的数组,一开始数组中每个元素都为0,要求支持以下两个操作:

1、区间[l,r]加自然数的平方数组,即
2、区间[l,r]查询区间和mod

输入描述

第一行输入
接下来行,对于每行,先读入一个整数
的值为时,还需读入两个整表示需要对区间[l,r]进行操作,让第一个元素加,第二个元素加,第三个元素加以此类推。
的值为时,还需读入两个整数表示查询l到r的元素和

输出描述

对于每一个,输出一行一个非负整数,表示l到r的区间和mod 

示例1

输入:

4 4
2 1 4
1 1 4
1 3 4
2 1 4

输出:

0
35

示例2

输入:

10 6
1 1 6
1 8 9
1 3 6
2 1 10
1 1 10
2 1 10

输出:

126
511

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 371ms, 内存消耗: 18448K, 提交时间: 2022-04-26 13:28:01

#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const int maxn = 5e5 + 5, mod = 1e9 + 7, inv6 = 166666668;
LL tr1[maxn], tr2[maxn], tr3[maxn], tr4[maxn];
int n, m;

inline int lowbit(int x){
    return x & -x;
}

void modify(int x, LL v){
    for(int i = x; i <= n; i += lowbit(i)){
        tr1[i] = (tr1[i] + v) % mod;
        tr2[i] = (tr2[i] + v * x % mod) % mod;
        tr3[i] = (tr3[i] + v * x % mod * x % mod) % mod;
        tr4[i] = (tr4[i] + v * x % mod * x % mod * x % mod) % mod;
    } 
}

LL query(int x){
    LL res = 0;
    for(int i = x; i; i -= lowbit(i))
        res = (res + tr1[i] * (x + 3) % mod * (x + 2) % mod * (x + 1) % mod
                   -(3LL * x * x % mod + 12LL * x % mod + 11) * tr2[i] % mod
                   + (3LL * x + 6) * tr3[i] % mod
                   - tr4[i]) % mod;
    return (res + mod) * inv6 % mod;
}

int main(){
    scanf("%d%d", &n, &m);
    while(m--){
        int op, l, r;
        scanf("%d%d%d", &op, &l, &r);
        if (op == 1){
            modify(l, 1);
            if (l + 1 <= n) modify(l + 1, 1);
            LL v = 1LL * (r - l + 1) * (r - l + 1) % mod;
            if (r + 1 <= n) modify(r + 1, (-v - 2 * (r - l + 1) - 1 + mod + mod) % mod);
            if (r + 2 <= n) modify(r + 2, 2 * v + 2 * (r - l + 1) - 1);
            if (r + 3 <= n) modify(r + 3, (-v + mod) % mod);
        }
        else printf("%lld\n", (query(r) - query(l - 1) + mod) % mod);
    }

}

上一题