牛牛的等差数列(线段树)


给定长度为n的初始序列a1,a2,⋯ ,an,接下来有q次操作:

  • 对于操作1,输入l,r,val,d表示对区间[l,r]加一个首项为val,公差为d的等差数列。
  • 对于操作2,输入l,r,m,表示询问区间[l,r]的和,并且对m取模。


第一行输入整数n (1≤n≤200000)。
接下来输入n个整数a1,a2⋯ ,ai (0≤ai≤109)。
接下来输入一个正整数q (1≤q≤2×10^5)。
接下来q行,每一行首先输入一个整数op∈{1,2}:
当op=1时,接下来输入l,r,val,d (1≤l,r≤n,0≤val,d≤10^9)表示第一种操作。
当op=2时,接下来输入l,r,m(1≤l,r≤n,3≤m≤25) 且m为素数,表示第二种操作。 


 

输出描述:

对于每个操作2,输出询问的答案。

示例1

输入

4
1 1 1 1
5
1 1 1 1 0
2 1 1 3
1 1 2 1 1
2 2 2 5
2 1 2 23

输出

2
3
6

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 7, mod = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23, Inv2 = mod - mod / 2;
typedef long long ll;
int n, q, a[maxn];
struct node
{
    ll sum, val, d;
} t[maxn * 4];
ll cal(int l, int r, int val, int d)
{
    ll cnt = r - l + 1;
    ll ans = (1LL * val + (1LL * val + (cnt - 1) * (ll)d) % mod) % mod;
    ans = (ans * cnt % mod * (ll)Inv2 % mod) % mod;
    return ans;
}
void pushup(int rt)
{
    t[rt].sum = (t[rt<<1].sum + t[rt<<1|1].sum) % mod;
}
void pushdown(int rt, int l, int r)
{
    if(t[rt].val != 0 || t[rt].d != 0)
    {
        int mid = (l + r) >> 1;
        t[rt<<1].sum = (t[rt<<1].sum + cal(l, mid, t[rt].val, t[rt].d)) % mod;
        t[rt<<1].val = (t[rt<<1].val + t[rt].val) % mod;
        t[rt<<1].d = (t[rt<<1].d + t[rt].d) % mod;

        t[rt].val = (t[rt].val + (ll)(mid + 1 - l) * t[rt].d % mod) % mod;

        t[rt<<1|1].sum = (t[rt<<1|1].sum + cal(mid + 1, r, t[rt].val, t[rt].d)) % mod;
        t[rt<<1|1].val = ((t[rt<<1|1].val + t[rt].val) % mod);
        t[rt<<1|1].d = (t[rt<<1|1].d + t[rt].d) % mod;

        t[rt].val = 0;
        t[rt].d = 0;
    }
}
void build(int rt, int l, int r)
{
    t[rt].val = t[rt].d = 0;
    t[rt].sum = 0;
    if(l == r)
    {
        t[rt].sum = a[l] % mod;
        return;
    }
    int mid = (l + r) >> 1;
    build(rt<<1, l, mid);
    build(rt<<1|1, mid + 1, r);
    pushup(rt);
}

void update(int rt, int l, int r, int L, int R, int val, int d)
{
    if(L <= l && R >= r)
    {
        t[rt].sum = (t[rt].sum + cal(l, r, val, d)) % mod;
        t[rt].val = (t[rt].val + val) % mod;
        t[rt].d = (t[rt].d + d) % mod;
        return ;
    }
    pushdown(rt, l, r);
    int mid = (l + r) >> 1;
    if(mid >= R) update(rt<<1, l, mid, L, R, val, d);
    else if(mid < L) update(rt<<1|1, mid + 1, r, L, R, val, d);
    else
    {
        update(rt<<1, l, mid, L, mid, val, d);
        val = (1LL * val + 1LL * (mid + 1 - L) * d % mod) % mod;
        update(rt<<1|1, mid + 1, r, mid + 1, R, val, d);
    }/*
    if(L<=mid)update(rt<<1,l,mid,L,R,val,d);
    if(R>mid)update(rt<<1|1,mid+1,r,L,R,val,d);*/
    pushup(rt);
}
ll query(int rt, int l, int r, int L, int R)
{
    if(L <= l && R >= r)
    {
        return t[rt].sum;
    }
    pushdown(rt, l, r);
    int mid = (l + r) >> 1;
    ll ans = 0;
    /* if(L <= mid) ans = (ans + query(rt<<1, l, mid, L, R)) % mod;
     if(R > mid) ans = (ans + query(rt<<1|1, mid + 1, r, L, R)) % mod;*/
    if(mid >= R) ans=(ans+query(rt<<1, l, mid, L, R))%mod;
    else if(mid < L) ans=(ans+query(rt<<1|1, mid + 1, r, L, R))%mod;
    else
    {
        ans=(ans+query(rt<<1, l, mid, L, mid)+query(rt<<1|1, mid + 1, r, mid + 1, R))%mod;
    }

    return ans;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    build(1, 1, n);
    scanf("%d", &q);
    int op;
    while (q--)
    {
        scanf("%d", &op);
        if(op == 1)
        {
            int l, r, val, d;
            scanf("%d%d%d%d", &l, &r, &val, &d);
            update(1, 1, n, l, r, val, d);
        }
        else
        {
            int l, r, m;
            scanf("%d%d%d", &l, &r, &m);
            printf("%lld\n", query(1, 1, n, l, r) % m);
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值