meirin
题目大意
在和积和的基础上加个区间增加 $b_i$ 的值,每次操作完询问和积和。
题解
推式子,发现加的数和原本的 $a_i,b_i$ 是独立的。然后没了,推个式子即可。
代码
const int N = 5e5 + 5, mod = 1e9 + 7;
inline ll Read() {
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
namespace Main {
int n, q;
ll a[N], b[N], ab[N], aa[N], bb[N], prea[N], ai[N], id[N], ans, inv2 = 500000004;
int main () {
n = Read(), q = Read();
for (int i = 1; i <= n; i++) a[i] = (Read() + a[i - 1]) % mod, id[i] = (id[i - 1] + i) % mod;
for (int i = 1; i <= n; i++)
prea[i] = (prea[i - 1] + a[i]) % mod, ai[i] = (ai[i - 1] + a[i] * i % mod) % mod;
for (int i = 1; i <= n; i++) b[i] = (Read() + b[i - 1]) % mod;
for (int i = n; i; i--) aa[i] = (a[i] + aa[i + 1]) % mod;
for (int i = n; i; i--) bb[i] = (b[i] + bb[i + 1]) % mod;
for (int i = n; i; i--) ab[i] = (a[i] * b[i] % mod + ab[i + 1]) % mod;
for (int l = 1; l <= n; l++) {
(ans += (n - l + 1) * a[l - 1] % mod * b[l - 1] % mod) %= mod;
(ans += ab[l]) %= mod;
ans = (ans - (a[l - 1] * bb[l] % mod + b[l - 1] * aa[l] % mod) % mod + mod) % mod;
}
for (; q--; ) {
ll l = Read(), r = Read(), k = Read();
while (k < 0) k += mod;
k %= mod;
// (n + 1) (k * )
ans = (ans + (((ai[r] - ai[l - 1] + mod) % mod * k % mod - (prea[r] - prea[l - 1] + mod) % mod * k % mod * (l - 1) % mod + mod) % mod + (prea[n] - prea[r] + mod) % mod * k % mod * (r - l + 1) % mod) * (n + 1) % mod) % mod;
ans = (ans - ((r * (r + 1) % mod * inv2 % mod - l * (l - 1) % mod * inv2 % mod + mod) % mod + (r - l + 1) * ((n - r - l + 1 + mod) % mod) % mod) * k % mod * prea[n] % mod + mod) % mod;
printf ("%lld\n", ans);
}
return 0;
}
}
int main () {
freopen("meirin.in", "r", stdin);
freopen("meirin.out", "w", stdout);
Main::main();
return 0;
}
EOF