题意
- 给定若干点和每个点的权值,查询若干次,每次查询输出将给定区间所有点移动到给定点的代价,代价为权值*距离
思路
-
肉眼可见的题目数据范围很大,暴力必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);
}
}