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

评论

暂无评论

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。

博客信息

作者
Jayun
时间
2023-10-26 08:03:20