题意

一个数轴上有一些储存点,每个储存点上都储存了一些东西,同时每一个储存点上都存有一些东西,现在我们要求把区间[i,j]上的东西移到x上的代价。

比如储物点i有x个东西,要运到储物点j,代价为x * dist( i , j )
dist就是储物点间的距离。

输入描述

第一行两个数表示n,m
第二行n-1个数,第i个数表示第i个储物点与第i+1个储物点的距离ai
第三行n个数,表示每个储物点的东西个数bi
之后m行每行三个数x l r
表示查询要把区间[l,r]储物点的物品全部运到储物点x的花费
每次查询独立

输出描述

对于每个询问输出一个数表示答案
答案对1000000007取模

解析

一看到这种把什么转移到什么上,区间啥啥啥的,就能想到要用前缀和解决这个问题,首先我们用一个数组对每一个储存点间的距离进行处理,这个很简单就是

然后就是对储物点上的物品价值也同样要进行处理

然后是代价,就是转移这一个物品的代价

那么每次对于区间的查询,如果x在l之前,那么把区间物品移动到出发的点(也就是轴最左边的点),多走的距离就是x到出发点距离,拿区间物品数目乘以距离再减掉就可以了。

对于x在r之后,那就是把这些物品从x移动到出发点,多走的部分就是,这些物品移动到出发点的花费,减掉就可以了。

对于在l,r之间的,分成前后两段分别按照前面两种方法求解就可以了。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=2e5+10,MOD=1e9+7;
ll 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])%MOD;
    for(int i=1;i<=n;i++){
        cin>>w[i];
        s[i]=(a[i]*w[i]%MOD+s[i-1]+s[i])%MOD;
        w[i]=(w[i]+w[i-1])%MOD;
    }
    while(m--){
        static int x,l,r,res;   cin>>x>>l>>r;
        if(x<=l){
            res=(s[r]-s[l-1]+MOD)%MOD; res=(res-(w[r]-w[l-1]+MOD)%MOD*a[x]%MOD+MOD)%MOD;  //这个地方需要注意一下取模的时候对减法的处理
        }else if(x>=r){
            res=((w[r]-w[l-1]+MOD)%MOD*a[x]%MOD-(s[r]-s[l-1]+MOD)%MOD+MOD)%MOD;
        }else{
            res=(s[r]-s[x-1]+MOD)%MOD; res=(res-(w[r]-w[x-1]+MOD)%MOD*a[x]%MOD+MOD)%MOD;
            res=(res+(w[x]-w[l-1]+MOD)%MOD*a[x]%MOD-(s[x]-s[l-1]+MOD)%MOD)%MOD;
        }
        res=(res+MOD)%MOD;
        cout<<res<<'\n';
    }
    return 0;
}