两次前缀和来解决,式子并不难推
将二次前缀想像成三角形会比较好理解
需维护:
1、距离前缀;
2、总价值(运费)前后缀;
3、个数前后缀;
具体式子详见代码
比较恶心的是取模意义下随时会有负数,并不太会处理,求大佬指教:
qz、hz中的1表示运费,2表示个数
#include<iostream>
#include<cstdio>
#include<algorithm>
#define LL long long
#define P 19260817
using namespace std;
const int MAXN = 200000 + 50;
LL qz1[MAXN],qz2[MAXN],hz1[MAXN],hz2[MAXN];
LL num[MAXN],dis[MAXN],ju[MAXN];
LL n,x,tot,m;
int l,r,v;
int main(){
scanf("%lld%lld",&n,&m);
for(int i = 2;i <= n;i ++){
scanf("%lld",&ju[i]);
dis[i] = (dis[i - 1]%P + ju[i]%P)%P;
}
for(int i = 1;i <= n;i ++){
scanf("%lld",&num[i]);
qz1[i] = (qz1[i - 1]%P + (tot%P*ju[i]%P)%P)%P;
tot = (num[i]%P + tot%P)%P;
qz2[i] = tot;
}
tot = 0;
for(int i = n;i >= 1;i --){
hz1[i] = (hz1[i + 1]%P + (tot%P*ju[i + 1]%P)%P)%P;
tot = (num[i]%P + tot%P)%P;
hz2[i] = tot;
}
/*for(int i = 1;i <= n;i ++){
printf("%lld ",hz1[i]);
}*/
for(int i = 1;i <= m;i ++){
scanf("%d%d%d",&v,&l,&r);
LL ans = 0;
if(v >= l && v <= r){
LL temp1 = qz1[v] - qz1[l];
while(temp1 < 0)temp1 += P;
LL tmp = dis[v] - dis[l];
while(tmp < 0)tmp += P;
temp1 = (temp1 - qz2[l - 1]%P*(tmp%P))%P;
while(temp1 < 0)temp1 += P;
while(tmp < 0)tmp += P;
LL temp2 = hz1[v] - hz1[r];
while(temp2 < 0)temp2 += P;
tmp = dis[r] - dis[v];
while(tmp < 0)tmp += P;
temp2 = (temp2 - hz2[r + 1]%P*(tmp%P))%P;
while(temp2 < 0)temp2 += P;
ans = (temp1%P + temp2%P)%P;
}
else if(v > r){
LL tmp = dis[r] - dis[l];
while(tmp < 0)tmp += P;
LL tmp2 = qz1[r] - qz1[l];
while(tmp2 < 0)tmp2 += P;
LL temp1 = tmp2 - (qz2[l - 1]%P*tmp)%P;
while(temp1 < 0)temp1 += P;
tmp = dis[v] - dis[r];
while(tmp < 0)tmp += P;
tmp2 = qz2[r] - qz2[l - 1];
while(tmp2 < 0)tmp2 += P;
temp1 = (temp1 + (tmp2*tmp)%P)%P;
ans = temp1;
}
else if(v < l){
LL tmp = dis[r] - dis[l];
while(tmp < 0)tmp += P;
LL tmp2 = hz1[l] - hz1[r];
while(tmp2 < 0)tmp2 += P;
LL temp1 = tmp2 - (hz2[r + 1]*(dis[r] - dis[l])%P)%P;
while(temp1 < 0)temp1 += P;
tmp = dis[l] - dis[v];
while(tmp < 0)tmp += P;
tmp2 = hz2[l] - hz2[r + 1];
while(tmp2 < 0)tmp2 += P;
temp1 = (temp1 + (tmp2*tmp)%P)%P;
ans = temp1;
}
printf("%lld\n",ans);
}
return 0;
}