题目链接:储物点的距离

看似是一道划分树的题目,但是因为没有修改操作,我们直接前缀和即可。

我们用前缀和维护区间的物品总数,以及维护区间物品全部移动到第一个点的花费。

然后就根据
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;
}