经典线段树问题。
我们知道等差数列加上等差数列还是一个等差数列。
所以我们线段树维护区间的总和,当前位置的值,和公差即可。
对于求区间和,因为模数是根据输入的,我们发现模数只到了25,所以我们考虑计算出来mod=lcm(1,2,3,....25)
这样的mod一定时1到25中任意一个数的倍数。那么我们输出的时候就可以保证输入的模数能够整除所求的区间和。
#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
const int mod = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23;
const int inv2 = mod / 2 + 1;
struct Treert {
int val, d, s;
};
Treert t[200010 * 4];
int n, q, op, l, r, x, y, a[200010];
void build(int rt , int l , int r)
{
if(l == r)
{
t[rt] = {0 , 0 , a[l]} ;
return ;
}
int mid = l + r >> 1 ;
build(rt << 1 , l , mid) ;
build(rt << 1 | 1 , mid + 1 , r) ;
t[rt] = {0 , 0 , (t[rt << 1].s + t[rt << 1 | 1].s) % mod };
return ;
}
void down(int rt , ll val , ll d , ll n)
{
t[rt].val = (t[rt].val + val) % mod ;
t[rt].d = (t[rt].d + d) % mod ;
t[rt].s = (t[rt].s + (val + val + (n - 1) * d % mod)% mod * n % mod * inv2 % mod) % mod ;
}
void update(int rt , ll l , ll r , ll ql , ll qr , ll val , ll d)
{
if(qr < l || r < ql) return ;
if(ql <= l && r <= qr)
{
down(rt , (val + (l - ql) * d % mod) % mod , d , r - l + 1) ;
return ;
}
int mid = l + r >> 1;
down(rt << 1 , t[rt].val , t[rt].d , mid - l + 1) ;
down(rt << 1 | 1 , (t[rt].val + (mid + 1 - l) * t[rt].d % mod )% mod , t[rt].d , r - mid) ;
t[rt].val = 0 , t[rt].d = 0 ;
update(rt << 1 , l , mid , ql , qr , val , d) ;
update(rt << 1 | 1 , mid + 1 , r , ql , qr ,val , d) ;
t[rt].s = (t[rt << 1].s + t[rt << 1 | 1].s ) % mod ;
return ;
}
ll ask(ll rt , ll l , ll r , ll ql , ll qr)
{
if(r < ql || l > qr) return 0 ;
if(ql <= l && r <= qr) return t[rt].s % mod ;
int mid = l + r >> 1;
down(rt << 1 , t[rt].val , t[rt].d , mid - l + 1) ;
down(rt << 1 | 1 , (t[rt].val + (mid + 1 - l) * t[rt].d % mod )% mod , t[rt].d , r - mid) ;
t[rt].val = 0 , t[rt].d = 0 ;
return (ask(rt << 1 , l , mid , ql , qr) + ask(rt << 1 | 1 , mid + 1 , r, ql , qr) )% mod ;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
build(1, 1, n);
scanf("%d", &q);
while (q--) {
scanf("%d%d%d%d", &op, &l, &r, &x);
if (op == 1) {
scanf("%d", &y);
update(1, 1, n, l, r, x, y);
} else printf("%d\n", ask(1, 1, n, l, r) % x);
}
return 0;
}

京公网安备 11010502036488号