luogu P3932 浮游大陆的68号岛

题目描述

妖精仓库里生活着黄金妖精们,她们过着快乐,却随时准备着迎接死亡的生活。
换用更高尚的说法,是随时准备着为这个无药可救的世界献身。
然而孩子们的生活却总是无忧无虑的,幼体的黄金妖精们过着天真烂漫的生活,自然也无暇考虑什么拯救世界之类的重任。
有一天小妖精们又在做游戏。这个游戏是这样的。
妖精仓库的储物点可以看做在一个数轴上。每一个储物点会有一些东西,同时他们之间存在距离。
每次他们会选出一个小妖精,然后剩下的人找到区间[l,r][l,r]储物点的所有东西,清点完毕之后问她,把这个区间内所有储物点的东西运到另外一个仓库的代价是多少?
比如储物点iixx个东西,要运到储物点jj,代价为
x \times \mathrm{dist}( i , j )x×dist(i,j)
dist就是仓库间的距离。
当然啦,由于小妖精们不会算很大的数字,因此您的答案需要对19260817取模。

输入格式:

第一行两个数表示n,mn,m
第二行n-1n1个数,第ii个数表示第ii个储物点与第i+1i+1个储物点的距离
第三行nn个数,表示每个储物点的东西个数
之后mm行每行三个数x l r
表示查询要把区间[l,r][l,r]储物点的物品全部运到储物点x的花费

输出格式:

对于每个询问输出一个数表示答案

输入样例#1:

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

输出样例#1:

125
72
9
70

说明

对于30%的数据,n , m \le 1000n,m1000
对于另外20%的数据,所有储物点间的距离都为1
对于另外20%的数据,所有储物点的物品数都为1
对于100%的数据 ,n , m <= 200000 ; a_i , b_i <= 2* 10^9

题解:

我们先将公式写出,就会发现可以通过求前缀和实现O(1)询问。注意,要多取模。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL mod = 19260817;
LL num[233333], val[233333];
LL sum1[233333], sum2[233333];
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; i++)
    {
        LL x;
        scanf("%lld", &x);
        num[i+1] = num[i] + x;
        num[i+1] %= mod;
    }
    for (int i = 1; i <= n; i++)
        scanf("%lld", &val[i]);
    for (int i = 1; i <= n; i++)
        sum1[i] = sum1[i-1]%mod + (val[i] * num[i]) % mod, sum1[i] %= mod, sum2[i] = sum2[i-1]%mod + val[i] % mod, sum2[i] %= mod;
    for (int i = 1; i <= m; i++)
    {
        int x, l, r;
        LL ans = 0;
        scanf("%d%d%d", &x, &l, &r);
        if (x < l)
            ans = sum1[r]%mod - sum1[l-1]%mod - (((sum2[r] - sum2[l-1])%mod) * num[x])%mod;
        else if (x > r)
            ans = (((sum2[r] - sum2[l-1])%mod) * num[x])%mod - sum1[r]%mod + sum1[l-1]%mod;
        else
        {
            ans = ((sum2[x] - sum2[l-1])%mod * num[x])%mod - sum1[x]%mod + sum1[l-1]%mod;
            ans += (sum1[r] - sum1[x])%mod - (sum2[r] - sum2[x])%mod * num[x]%mod;
        }
        ans %= mod;
        while (ans < 0)
            ans += mod;
        printf("%lld\n", ans);
    }
    return 0;
}

 

上一篇
下一篇