这题数据好多细节,气死本萌妹了
Description
一个数轴,每一个储物点会有一些东西,同时它们之间存在距离。
每次给个区间 ,查询把这个区间内所有储物点的东西运到另外一个储物点的代价是多少?
比如储物点 有
个东西,要运到储物点
,代价为
就是储物点间的距离。
Solution
对于一个区间 , 总的代价为
对于最终点 , 我们可以分三种情况:
, 那么上面式子里的绝对值去掉得到
, 那么上面式子里的绝对值去掉得到
, 那么对区间
分别做上述的操作即可
观察发现可以维护两个前缀和, 和
, 那么上述每次查询操作就能够
注意到数据好大, 前缀和都要注意取模,然后负数取模也要注意。
Code
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod = 1e9 + 7;
const int N = 2e5 + 5;
ll a[N], b[N], c[N], sum[N];
int main() {
ios::sync_with_stdio(false), cin.tie(0);
int n, m;
cin >> n >> m;
for(int i = 2; i <= n; i++) {
cin >> a[i];
a[i] = (a[i - 1] + a[i]) % mod;
}
for(int i = 1; i <= n; i++) cin >> b[i], c[i] = (a[i] * b[i]) % mod, b[i] = (b[i] + b[i - 1]) % mod, sum[i] = (sum[i - 1] + c[i]) % mod;
while(m--) {
int l, r, x;
cin >> x >> l >> r;
ll ans = 0;
if(x >= r) {
ans = a[x] * ((b[r] - b[l - 1] + mod) % mod) % mod;
ans = (ans - ((sum[r] - sum[l - 1] + mod) % mod) + mod) % mod;
ans = (ans + mod) % mod;
cout << ans << "\n";
} else if(x <= l) {
ans = (sum[r] - sum[l - 1] + mod) % mod;
ans = (ans - a[x] * ((b[r] - b[l - 1] + mod) % mod) + mod) % mod;
ans = (ans + mod) % mod;
cout << ans << "\n";
} else {
ll ans1 = (sum[r] - sum[x - 1] + mod) % mod;
ans1 = (ans1 - (a[x] * ((b[r] - b[x - 1]) + mod % mod)) + mod) % mod;
ans1 = (ans1 + mod) % mod;
ll ans2 = (a[x] * ((b[x - 1] - b[l - 1] + mod) % mod)) % mod;
ans2 = (ans2 - ((sum[x - 1] - sum[l - 1] + mod) % mod) + mod) % mod;
ans2 = (ans2 + mod) % mod;
cout << (ans1 + ans2) % mod << "\n";
}
}
return 0;
} 
京公网安备 11010502036488号