【每日一题】5月15日储物点的距离

储物点的距离

https://ac.nowcoder.com/acm/problem/14683

解题思路

前缀和,千万千万注意减法取模……我半个多小时。。
区间问题,居然要全部转移那么最简单模拟的话,出题人变态一点,每个区间都是最左端和最右端。时间复杂度毫无疑问爆炸了
这时候,昨天的直播课,雨巨小姐姐刚好又说到了区间问题的解决办法!!吹爆。每个步骤都去模拟太蠢了,想想能不能用前缀和代替一下。
区间问题解决办法一般有前缀和,树状数组,线段树,码量也是依次增大,当然能力也是依次增大。
放到这个题目上,给出每个相邻点距离,我们选取1作为源点,一次前缀和,可以得到每个点到1的距离。
第二个是物品数量,那么一次前缀和就可以得到区间内有多少物品。
第三个,这个也是比较不好想的也是本题解题的关键。新开一个数组,存放每个位置全部物品转移到源点的花费前缀和。
那么每次对于区间的查询,如果x在l之前,那么把区间物品移动到源点,多走的距离就是x到源点距离,拿区间物品数目乘以距离再减掉就行了。
对于x在r之后,那就是把这些物品从x移动到源点,多走的部分就是,这些物品移动到源点的花费,减掉即可。
对于在l,r之间的,分成前后两段分别按照前面两种方法求解即可。

千万千万千万注意减法的MOD运算吖,我哭了。

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#pragma GCC optimize(3)
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();    return s * w; }
inline void write(ll x) { if (!x) { putchar('0'); return; } char F[200]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-');    int cnt = 0;    while (tmp > 0) { F[cnt++] = tmp % 10 + '0';        tmp /= 10; }    while (cnt > 0)putchar(F[--cnt]); }

const int N = 2e5 + 7;
const int MOD = 1e9 + 7;
ll a[N], b[N], c[N];

int main() {
    int n = read(), m = read();
    for (int i = 2; i <= n; ++i)    a[i] = read(), a[i] = (a[i] + a[i - 1]) % MOD;
    for (int i = 1; i <= n; ++i) {
        b[i] = read();
        c[i] = (c[i - 1] + a[i] * b[i]) % MOD;
        b[i] = (b[i - 1] + b[i]) % MOD;
    }
    while (m--) {
        int x = read(), l = read(), r = read();
        ll ans = 0;
        if (x <= l) {
            ans = (c[r] - c[l - 1] + MOD) % MOD;
            ans = (ans - (b[r] - b[l - 1] + MOD) % MOD * a[x] % MOD + MOD) % MOD;
        }
        else if (x >= r) {
            ans = (b[r] - b[l - 1] + MOD) % MOD * a[x] % MOD;
            ans = (ans - (c[r] - c[l - 1] + MOD) % MOD + MOD) % MOD;
        }
        else {
            ans = (c[r] - c[x] + MOD) % MOD;
            ans = (ans - (b[r] - b[x] + MOD) % MOD * a[x] % MOD + MOD) % MOD;
            ans = (ans + (b[x] - b[l - 1] + MOD) % MOD * a[x] % MOD - (c[x] - c[l - 1] + MOD) % MOD + MOD) % MOD;
        }
        write(ans), putchar('\n');
    }
    return 0;
}
每日一题 文章被收录于专栏

每日一题

全部评论

相关推荐

11-29 11:21
门头沟学院 Java
总包48.5w,意想不到的价格
想开了的垂耳兔很喜欢拱白菜:转人工
点赞 评论 收藏
分享
10-24 11:10
山西大学 Java
若梦难了:哥们,面试挂是很正常的。我大中厂终面挂,加起来快10次了,继续努力吧。
点赞 评论 收藏
分享
11-11 14:21
西京学院 C++
无敌混子大王:首先一点,不管学校层次怎么样,教育经历放在第一页靠上位置,第一页看不到教育经历,hr基本直接扔掉了
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
11-27 10:28
点赞 评论 收藏
分享
评论
2
收藏
分享
牛客网
牛客企业服务