zoukankan      html  css  js  c++  java
  • hihocoder offer收割编程练习赛11 D 排队接水

    思路:

    莫队算法+树状数组。

    莫队算法的基本思想是对大量要查询的区间进行离线处理,按照一定的顺序计算,来降低复杂度。概括来说,我们在知道了[l, r]的解,并且可以通过一个较低的复杂度推出[l - 1, r], [l, r - 1], [l + 1, r], [l, r + 1]的解的情况下,则可使用该算法。

    对该算法比较好的介绍:

    1.https://blog.sengxian.com/algorithms/mo-s-algorithm

    2.http://blog.csdn.net/bossup/article/details/39236275

    在本题中,对于一个区间[l, r],实际上是求a[l] * (r - l + 1) + a[l + 1] * (r - l) +... + a[r] * 1。

    那么在知道了[l, r]的解的前提下,如何转移到[l', r']呢?

    我们可以观察一个简单的情况:[l, r] -> [l - 1, r]。比如[1, 2, 3, 4] -> [3, 1, 2, 3, 4]。

    对于这个例子,假设原来的解为res。那么在左边加上一个‘3’之后,新的解res_new为

    1 * 5 + 2 * 4 + 3 * 3 + 3 * 2 + 4 * 1 =

    1 * 4 + 2 * 3 + 3 * 2 + 4 * 1 + 1 + 2 + 3 * 3 =

    res + 1 + 2 + 3 * 3。

    实际上就是原来的解res + 原来的区间内比3小的数的和 + 3 * (原来的区间内大于等于3的数的个数 + 1);

    反过来,[3, 1, 2, 3, 4] -> [1, 2, 3, 4]的过程类似。

    我们可以使用两个树状数组来维护变化的部分。具体来说其中一个维护大于等于3的数的个数,另一个维护小于3的数的和即可。

    实现:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 using namespace std;
      6 typedef long long ll;
      7 
      8 const int N = 200000;
      9 
     10 int t, n, m, L, R, a[N + 5], block;
     11 ll tot = 0, ans[N + 5];
     12 ll bit1[N + 5]; //统计个数
     13 ll bit2[N + 5]; //统计和
     14 
     15 struct query
     16 {
     17     int l, r, id;
     18 };
     19 query Q[N + 5];
     20 
     21 bool cmp(const query & x, const query & y)
     22 {
     23     if (x.l / block != y.l / block)
     24         return x.l / block < y.l / block;
     25     return x.r < y.r;
     26 }
     27 
     28 void bit_add(ll * bit, int i, int x)
     29 {
     30     if (i == 0)
     31         return;
     32     while (i <= N)
     33     {
     34         bit[i] += x;
     35         i += i & -i;
     36     }
     37 }
     38 
     39 ll bit_sum(ll * bit, int i)
     40 {
     41     ll s = 0;
     42     while (i)
     43     {
     44         s += bit[i];
     45         i -= i & -i;
     46     }
     47     return s;
     48 }
     49 
     50 ll bit_query(ll * bit, int l ,int r)
     51 {
     52     return bit_sum(bit, r) - bit_sum(bit, l - 1);
     53 }
     54 
     55 void Add(int pos)
     56 {
     57     tot += (ll)a[pos] * (bit_query(bit1, a[pos], N + 1) + 1);
     58     tot += bit_query(bit2, 1, a[pos] - 1);
     59     bit_add(bit1, a[pos], 1);
     60     bit_add(bit2, a[pos], a[pos]);
     61 }
     62 
     63 void Del(int pos)
     64 {
     65     tot -= (ll)a[pos] * bit_query(bit1, a[pos], N + 1);
     66     tot -= bit_query(bit2, 1, a[pos] - 1);
     67     bit_add(bit1, a[pos], -1);
     68     bit_add(bit2, a[pos], -a[pos]);
     69 }
     70 
     71 void init()
     72 {
     73     block = sqrt(n);
     74     L = R = 1;
     75     tot = a[1];
     76     memset(bit1, 0, sizeof(bit1));
     77     memset(bit2, 0, sizeof(bit2));
     78     bit_add(bit1, a[1], 1);
     79     bit_add(bit2, a[1], a[1]);
     80 }
     81 
     82 int main()
     83 {
     84     cin >> t;
     85     while (t--)
     86     {
     87         cin >> n >> m;
     88         for (int i = 1; i <= n; i++)
     89         {
     90             scanf("%d", &a[i]);
     91         }
     92         init();
     93         for (int i = 0; i < m; i++)
     94         {
     95             scanf("%d %d", &Q[i].l, &Q[i].r);
     96             Q[i].id = i;
     97         }
     98         sort(Q, Q + m, cmp);
     99         for (int i = 0; i < m; i++)
    100         {
    101             while (L < Q[i].l)
    102                 Del(L++);
    103             while (L > Q[i].l)
    104                 Add(--L);
    105             while (R < Q[i].r)
    106                 Add(++R);
    107             while (R > Q[i].r)
    108                 Del(R--);
    109             ans[Q[i].id] = tot;
    110         }
    111         for (int i = 0; i < m; i++)
    112         {
    113             printf("%lld
    ", ans[i]);
    114         }
    115     }
    116     return 0;
    117 }
  • 相关阅读:
    ArcGIS.Server.9.3.DotNet的ADF与ASP.NET AJAX
    ArcGIS.Server.9.3和ArcGIS API for JavaScript保存自定义图形(十)
    android开发我的新浪微博客户端载入页面UI篇(1.1)
    ArcGIS.Server.9.3和ArcGIS API for JavaScript实现距离量算和面积量算(九)
    ArcGIS.Server.9.3和ArcGIS API for JavaScript实现点、线、面的buffer分析(十一)
    android开发我的新浪微博客户端载入页面sqlite篇(1.2)
    市净率PB
    转 未来的GDI:WPF技术纵览
    转 LUA语言学习教程
    sl下的两种跨线程访问方式
  • 原文地址:https://www.cnblogs.com/wangyiming/p/6626853.html
Copyright © 2011-2022 走看看