zoukankan      html  css  js  c++  java
  • 【每日一题】30.储物点的距离 (区间处理,前缀和/线段树//树状数组)

    补题链接:Here

    算法涉及:前缀和,思维

    一个数轴,每一个储物点会有一些东西,同时它们之间存在距离。

    每次给个区间 ([l,r]) ,查询把这个区间内所有储物点的东西运到另外一个储物点的代价是多少?

    比如储物 (i) 点有(x) 个东西,要运到储物点 (j) ,代价为 (x*dit(i,j))

    dist(i, j) = abs(i - j) 就是储物点间的距离。

    【解题思路】

    对于一个区间 ([l, r]) , 总的代价为 (sumlimits_{i = l}^{r}b[i] * abs(a[i] - a[x]))
    对于最终点 (x) , 我们可以分三种情况:

    • (rle x),那么上面式子里的绝对值去掉得到 (sumlimits_{i = l}^{r}b[i] * abs(a[i] - a[x]) = a[x]sumlimits_{i = l}^{r}b[i] - sumlimits_{i = l}^{r}a[i]b[i])

    • (xle l),那么上面式子里的绝对值去掉得到(sumlimits_{i = l}^{r}b[i] * abs(a[i] - a[x]) = -a[x]sumlimits_{i = l}^{r}b[i] + sumlimits_{i = l}^{r}a[i]b[i])

    • (l < x < r) , 那么对区间 ([l,x-1],[x,r]) 分别做上述的操作即可

    观察发现可以维护两个前缀和, (sumlimits_{i = l}^{r}a[i]b[i])(sumlimits_{i = l}^{r}b[i]) , 那么上述每次查询操作就能够 (mathcal{O}(1))

    • 最后万分提醒,取模、取模再取模。。。Debug 超久
    using ll = long long;
    const int mod = 1e9 + 7;
    const int N = 2e5 + 10;
    ll a[N], b[N], c[N], sum[N];
    void solve() {
        int n, m;
        cin >> n >> m;
        for (int i = 2; i <= n; ++i) {
            cin >> a[i]; // n - 1个数,第i个数表示第i个储物点与第i+1个储物点的距离ai
            a[i] = (a[i - 1] + a[i]) %  mod;
        }
        for (int i = 1; i <= n; ++i) {
            cin >> b[i]; // 每个储物点的东西个数bi
            c[i] = (a[i] * b[i]) % mod;
            b[i] = (b[i] + b[i - 1]) % mod;
            sum[i] = (sum[i - 1] + c[i]) % mod;
        }
        int l, r, x;
        while (m--) {
            cin >> x >> l >> r;
            ll ans = 0;
            if (x >= r) { // 情况 1
                ans = a[x] * ((b[r] - b[l - 1] + mod) % mod) % mod;
                ans = (ans - ((sum[r] - sum[l - 1] + mod) % mod) + mod) % mod;
                ans = (ans + mod) % mod;
                cout << ans << "
    ";
            } else if (l >= x) { // 情况 2
                ans = (sum[r] - sum[l - 1] + mod) % mod;
                ans = (ans - a[x] * ((b[r] - b[l - 1] + mod) % mod) + mod)  % mod;
                ans = (ans + mod) % mod;
                cout << ans << "
    ";
            } else { // 情况 3
                ll ans1 = (sum[r] - sum[x - 1] + mod) % mod;
                ans1 = (ans1 - (a[x] * ((b[r] - b[x - 1]) + mod % mod)) + mod) % mod;
                ans1 = (ans1 + mod) % mod;
                ll ans2 = (a[x] * ((b[x - 1] - b[l - 1] + mod) % mod)) % mod;
                ans2 = (ans2 - ((sum[x - 1] - sum[l - 1] + mod) % mod) + mod) % mod;
                ans2 = (ans2 + mod) % mod;
                cout << (ans1 + ans2) % mod << "
    ";
            }
        }
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    【万里征程——Windows App开发】使用华丽丽的字体
    【万里征程——Windows App开发】SemanticZoom视图切换
    用Alt码打出Pi以及各式各样的符号
    3行代码列出硬盘上所有文件及文件夹
    【万里征程——Windows App开发】ListView&GridView之分组
    【万里征程——Windows App开发】ListView&GridView之添加数据
    从头认识js-js中的对象
    js中如何判断属性是对象实例中的属性还是原型中的属性
    从头认识js-HTML中使用JavaScript
    从头认识js-js的发展历史
  • 原文地址:https://www.cnblogs.com/RioTian/p/14791506.html
Copyright © 2011-2022 走看看