这是一个前缀和+分类讨论题,难点在前缀和应该要做成什么样子和算不同情况应该怎么计算。
前缀和有3个为:距离前缀和dis,数量前缀和num,1~i号仓库的物品都运送到1号点的前缀和sum。

然后分成3种情况讨论:
x在区间右边,x在区间左边,x在区间中间。
计算方法只有两种:把区间内的东西运送到左边和运送到右边。

对于第一种计算方法级记作calR:
先算出区间内的数量num[r]-num[l-1],然后我们知道前缀和sum是1~i号点都送到1号点的和,那么sum[r]-sum[l-1]就是这段区间送到1号点的和,然后减去1到x这段距离dis[x]就行了
即:图片说明 (这里就不取模了)

对于第二种计算放假记作calL:
同时也先算出区间数量,然后我们把区间数量×dis[x],这样会多出sum[r]-sum[l-1]这段距离,减掉即可。
即:图片说明

然后对于三种情况:
第一种:直接calL(l,r,x)
第二种:直接calR(l,r,x)
第三种:calL(x,z,z)+calR(z,y,z)

代码:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#define fs first
#define se second
#define pb push_back
#define cppio ios::sync_with_stdio(false);cin.tie(0)
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef vector<int> VI;

const int maxn=1e6+6;
const ll inf=0x3f3f3f3f;
const ll mod=1e9+7;
int n,m;
ll num[maxn];
ll dis[maxn];
ll sum[maxn];

ll calL(int l,int r,int x){
    ll ans=0;
    ll tnum=(num[r]-num[l-1]+mod)%mod;
    ans=tnum*dis[x]%mod;
    ll tmp=(sum[r]-sum[l-1]+mod)%mod;
    ans=(ans+mod-tmp)%mod;
    return ans;
}

ll calR(int l,int r,int x){
    ll ans=0;
    ll tnum=(num[r]-num[l-1]+mod)%mod;
    ans=(sum[r]+mod-sum[l-1])%mod;
    ans=(ans-tnum*dis[x]%mod+mod)%mod;
    return ans;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i=2;i<=n;i++){
        scanf("%lld",dis+i);
        dis[i]=(dis[i-1]+dis[i])%mod;
    }
    for(int i=1;i<=n;i++){
        scanf("%lld",num+i);
        sum[i]=(sum[i-1]+num[i]*dis[i])%mod;
        num[i]=(num[i-1]+num[i])%mod;
    }
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&z,&x,&y);
        ll ans=0;
        if(z>=y){
            ans=calL(x,y,z);
        }
        else if(z<=x){
            ans=calR(x,y,z);
        }
        else{
            ans=(calL(x,z,z)+calR(z,y,z))%mod;
        }
        printf("%lld\n",ans%mod);
    }
    return 0;
}