题目链接:储物点的距离
看似是一道划分树的题目,但是因为没有修改操作,我们直接前缀和即可。
我们用前缀和维护区间的物品总数,以及维护区间物品全部移动到第一个点的花费。
然后就根据
l,r,x之间的关系,推一推式子就行了。
AC代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+10,p=1e9+7;
int n,m,a[N],w[N],s[N];
signed main(){
ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
cin>>n>>m;
for(int i=2;i<=n;i++) cin>>a[i],a[i]=(a[i]+a[i-1])%p;
for(int i=1;i<=n;i++){
cin>>w[i];
s[i]=(a[i]*w[i]%p+s[i-1]+s[i])%p;
w[i]=(w[i]+w[i-1])%p;
}
while(m--){
static int x,l,r,res; cin>>x>>l>>r;
if(x<=l){
res=(s[r]-s[l-1]+p)%p; res=(res-(w[r]-w[l-1]+p)%p*a[x]%p+p)%p;
}else if(x>=r){
res=((w[r]-w[l-1]+p)%p*a[x]%p-(s[r]-s[l-1]+p)%p+p)%p;
}else{
res=(s[r]-s[x-1]+p)%p; res=(res-(w[r]-w[x-1]+p)%p*a[x]%p+p)%p;
res=(res+(w[x]-w[l-1]+p)%p*a[x]%p-(s[x]-s[l-1]+p)%p)%p;
}
res=(res+p)%p;
cout<<res<<'\n';
}
return 0;
}