分析:
前缀和\(sum_i\)表示 将仓库\(1-i\)所有物品转移到\(1\)号仓库花费\(sum2_i\)表示 将仓库\(1-i\)所有物品转移到\(n\)号仓库花费\(dis_i\)表示\(i\)号仓库到\(1\)号仓库距离\(num_i\)表示仓库\(1-i\)物品总个数
分\(3\)种情况:
- \(x\)在\(l\)左边
- \(x\)在\(r\)右边
- \(x\)在\(l,r\)之间
情况\(1:\)运用区间和 算出将\([l,r]\)物品运到\(1\)号仓库花费 再减多余的\([1,x]\)花费
情况\(2\)用\(sum2\)数组 同理
情况\(3\) 将\([l,r]\)拆成\([l,x]\) \([x,r]\) 然后和上面一样计算
减去多余花费最好用\(dis\times num\) 因为用\(sum\)直接算的话 还要处理\([x,l]\) \([r,x]\)的花费总和
要不断取\(mod\) 以及因为是减法取\(mod\) 出现负数要加回去
CODE:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+5,Mod=19260817;
int n,m;
ll a[N],dis[N],sum[N],sum2[N],num[N];
ll toL(int x,int l,int r){return ((sum[r]-sum[l-1])%Mod-(num[r]-num[l-1])*dis[x]%Mod+Mod)%Mod;}
ll toR(int x,int l,int r){return ((sum2[r]-sum2[l-1])%Mod-(num[r]-num[l-1])*(dis[n]-dis[x])%Mod+Mod)%Mod;}
int main(){
scanf("%d%d",&n,&m);
for(int i=2;i<=n;i++)
{
scanf("%lld",&dis[i]);
(dis[i]+=dis[i-1])%=Mod;
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
num[i]=(num[i-1]+a[i])%Mod;
sum[i]=(a[i]*dis[i])%Mod;
sum2[i]=(a[i]*(dis[n]-dis[i]))%Mod;
}
sum[1]=sum2[n]=0;
for(int i=1;i<=n;i++)
{
(sum[i]+=sum[i-1])%=Mod;
(sum2[i]+=sum2[i-1])%=Mod;
}
while(m--)
{
int x,l,r;
ll ans=0;
scanf("%d%d%d",&x,&l,&r);
if(x<=l)
{
ans=toL(x,l,r);
while(ans<0) ans+=Mod;
printf("%lld\n",ans);
}
else if(x>=r)
{
ans=toR(x,l,r);
while(ans<0) ans+=Mod;
printf("%lld\n",ans);
}
else
{
ans=(toL(x,x,r)+toR(x,l,x))%Mod;
while(ans<0) ans+=Mod;
printf("%lld\n",ans);
}
}
return 0;
}