经典线段树问题。
我们知道等差数列加上等差数列还是一个等差数列。
所以我们线段树维护区间的总和,当前位置的值,和公差即可。
对于求区间和,因为模数是根据输入的,我们发现模数只到了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; }