题意

  • 给定若干点和每个点的权值,查询若干次,每次查询输出将给定区间所有点移动到给定点的代价,代价为权值*距离

思路

  • 肉眼可见的题目数据范围很大,暴力必T就别抱有幻想了

  • 差分的给出了坐标,可以求前缀和得到每个点的真实坐标

  • 让我们算代价,对代价的公式进行推导:

    此时,此时我们试图消去绝对值,讨论a[i]和a[x]的大小,也就是x和l,r的关系

  • 最终可以得到,总代价%%和以及有关

  • 维护三个前缀和就可以在的复杂度内获得答案

  • 记得取模

AC代码

#include<bits/stdc++.h>
using namespace std;
long long p=1e9+7;
long long a[202020],b[202020],c[202020];
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=2;i<=n;i++){
        scanf("%lld",&a[i]);
        a[i]+=a[i-1];
        a[i]%=p;
    }
    for(int i=1;i<=n;i++){
        long long bb;
        scanf("%lld",&bb);
        b[i]=b[i-1]+bb;
        c[i]=c[i-1]+bb*a[i];
        b[i]%=p;
        c[i]%=p;
    }
    for(int i=0;i<m;i++){
        int l,r,x;
        scanf("%d%d%d",&x,&l,&r);
        long long ans=0;
        if(x>=r){
            ans=((((b[r]-b[l-1])+p)%p)*a[x]%p-(((c[r]-c[l-1])+p)%p)+p)%p;
        }else if(x<=l){
            ans=((((c[r]-c[l-1])+p)%p)-(((b[r]-b[l-1])+p)%p)*a[x]%p+p)%p;
        }else{
            ans=((((b[x-1]-b[l-1])+p)%p)*a[x]%p-(((c[x-1]-c[l-1])+p)%p)+p)+((((c[r]-c[x])+p)%p)-(((b[r]-b[x])+p)%p*a[x]%p)+p);
        }
        printf("%lld\n",ans%p);
    }
}