有一天小妖精们又在做游戏。这个游戏是这样的。
妖精仓库的储物点可以看做在一个数轴上。每一个储物点会有一些东西,同时他们之间存在距离。
每次他们会选出一个小妖精,然后剩下的人找到区间[l,r][l,r][l,r]储物点的所有东西,清点完毕之后问她,把这个区间内所有储物点的东西运到另外一个仓库的代价是多少?
比如储物点iii有xxx个东西,要运到储物点jjj,代价为
x×dist(i,j)x \times \mathrm{dist}( i , j )x×dist(i,j)
dist就是仓库间的距离。
当然啦,由于小妖精们不会算很大的数字,因此您的答案需要对19260817取模。
输入输出格式
输入格式:第一行两个数表示n,mn,mn,m
第二行n−1n-1n−1个数,第iii个数表示第iii个储物点与第i+1i+1i+1个储物点的距离
第三行nnn个数,表示每个储物点的东西个数
之后mmm行每行三个数x l r
表示查询要把区间[l,r][l,r][l,r]储物点的物品全部运到储物点x的花费
输出格式:对于每个询问输出一个数表示答案
输入输出样例
5 5 2 3 4 5 1 2 3 4 5 1 1 5 3 1 5 2 3 3 3 3 3 1 5 5
125 72 9 0 70
说明
对于30%的数据,n,m≤1000n , m \le 1000n,m≤1000
对于另外20%的数据,所有储物点间的距离都为1
对于另外20%的数据,所有储物点的物品数都为1
对于100%的数据 ,n,m≤200000;ai,bi<=2⋅109 n , m \le 200000 ; a_i , b_i <= 2\cdot 10^9n,m≤200000;ai,bi<=2⋅109
首先我们设viv_ivi表示第i个位置上的物品数量,维护一个前缀和disidis_idisi表示第i个位置到第一个位置的距离
由此我们可以得出以下公式:ans=∑i=1nvi∣disi−disx∣ans=\sum_{i=1}^{n}v_i|dis_i-dis_x|ans=∑i=1nvi∣disi−disx∣化简得:ans=∑i=1n∣vidisi−vidisx∣ans=\sum_{i=1}^{n}|v_i dis_i-v_i dis_x|ans=∑i=1n∣vidisi−vidisx∣我们发现:对于每一个i,它的vidisiv_i dis_ividisi是一个定值,那么我们就也用一个前缀和mulimul_imuli来维护第i个位置上的物品数量与disidis_idisi的乘积
最后在维护一个前缀和sumisum_isumi储存前i个位置中物品的总量
当我们求最终答案的时候需要考虑三种情况:
1 对于输入的x、l、r满足x≤lx \leq lx≤l
这种情况的答案ans=(mulr−mull−1)−(sumr−suml−1)disians=(mul_{r}-mul_{l-1})-(sum_{r}-sum_{l-1})dis_ians=(mulr−mull−1)−(sumr−suml−1)disi
2 对于输入的x、l、r满足r≤xr \leq xr≤x
很显然这种情况的ans=sumr−suml−1)disi−(mulr−mull−1)ans=sum_{r}-sum_{l-1})dis_i-(mul_{r}-mul_{l-1})ans=sumr−suml−1)disi−(mulr−mull−1)
3 需要注意的就是l≤x≤rl \leq x \leq rl≤x≤r的这种情况
对于区间内x之前的部分,有ans=(sumx−1−suml−1)disx−(mulx−1−mull−1)ans=(sum_{x-1}-sum_{l-1})dis_x-(mul_{x-1}-mul_{l-1})ans=(sumx−1−suml−1)disx−(mulx−1−mull−1)
对于区间内x之后的部分,有ans=(mulr−mulx)−(sumr−sumx)disxans=(mul_{r}-mul_{x})-(sum_{r}-sum_{x})dis_{x}ans=(mulr−mulx)−(sumr−sumx)disx
然后我们把两个ans加起来就是这种情况的答案
#include<iostream>
#define f(i,l,r) for(i=(l);i<=(r);i++)
using namespace std;
const int MAXN=200005,MOD=19260817;
long long n,m,dis[MAXN],w[MAXN];
long long c1[MAXN],c2[MAXN];
long long Plus(long long a,long long b)
{
a=(a+MOD)%MOD;b=(b+MOD)%MOD;
return (a+b)%MOD;
}
long long minu(long long a,long long b)
{
a=(a+MOD)%MOD;b=(b+MOD)%MOD;
return (a-b+MOD)%MOD;
}
long long mult(long long a,long long b)
{
a=(a+MOD)%MOD;b=(b+MOD)%MOD;
return (a*b)%MOD;
}
int main()
{
ios::sync_with_stdio(false);
int i,j,x,l,r;
long long ans;
cin>>n>>m;
f(i,2,n){
cin>>dis[i];
dis[i]=Plus(dis[i],dis[i-1]);
}
f(i,1,n){
cin>>w[i];
c1[i]=Plus(mult(w[i],dis[i]),c1[i-1]);
c2[i]=Plus(c2[i-1],w[i]);
}
f(i,1,m){
cin>>x>>l>>r;
if(x<=l){
ans=minu(minu(c1[r],c1[l-1]),mult(dis[x],minu(c2[r],c2[l-1])));
}
else if(x>=r){
ans=minu(mult(dis[x],minu(c2[r],c2[l-1])),minu(c1[r],c1[l-1]));
}
else{
ans=minu(mult(dis[x],minu(c2[x],c2[l-1])),minu(c1[x],c1[l-1]));
ans=Plus(ans,minu(minu(c1[r],c1[x-1]),mult(dis[x],minu(c2[r],c2[x-1]))));
}
cout<<(ans+MOD)%MOD<<endl;
}
return 0;
}