zoukankan      html  css  js  c++  java
  • Codeforces 86D

    题目大意:

    给定长为N的序列a[1..N]和T次询问,每次询问指定一个子段a[L..R],设某个数v在该子段中出现k(v)次,那么该次询问的结果为Σv*k(v)*k(v)。

    N,T≤2e5,1≤a[i]≤1e6。

    莫队算法初次听起来可能感觉很神奇,不过原理和实现方法都很简单。这里有篇很不错的英文讲解:https://www.hackerearth.com/zh/practice/notes/mos-algorithm/

    应用莫队算法的前提:(1)静态序列,无修改操作;(2)离线询问。

    莫队算法的流程:(直接从上边的网址Ctrl-C过来的)

    Step 1:
        Denote BLOCK_SIZE = sqrt(N);
    Step 2:
        Rearrange all queries in a way we will call “Mo’s order”. It is defined like this: [L1, R1] comes earlier than [L2, R2] in Mo’s order if and only if:
       a) L1 / BLOCK_SIZE < L2 / BLOCK_SIZE
       b) L1 / BLOCK_SIZE == L2 / BLOCK_SIZE && R1 < R2
    Step 3:
        Maintain segment [mo_left, mo_right] for which we know Func([mo_left, mo_right]). Initially, this segment is empty. We set mo_left = 0 and mo_right = -1;(注:原文约定序列下标从0开始)
    Step 4:
        Answer all queries following Mo’s order. Suppose the next query you want to answer is [L, R]. Then you perform these steps:
       a) while mo_right is less than R, extend current segment to [mo_left, mo_right + 1];
       b) while mo_right is greater than R, cut current segment to [mo_left, mo_right - 1];
       c) while mo_left is greater than L, extend current segment to [mo_left - 1, mo_right];
       d) while mo_left is less than L, cut current segment to [mo_left + 1, mo_right].

    本题的代码如下:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 
     5 using LL = long long;
     6 
     7 const int blockSize = 450;
     8 const int maxN = (int)2e5 + 10;
     9 
    10 int A[maxN], N, T;
    11 int C[(int)1e6 + 1];
    12 LL curAns;
    13 
    14 struct Query
    15 {
    16     int id;
    17     int left, right;
    18     int blockId;
    19     LL ans;
    20 
    21     bool operator < (const Query& rhs) const {
    22         return blockId < rhs.blockId || (blockId == rhs.blockId && right < rhs.right);
    23     }
    24 };
    25 Query query[maxN];
    26 
    27 void input()
    28 {
    29     scanf("%d%d", &N, &T);
    30     for (int i = 1; i <= N; i++)
    31         scanf("%d", A + i);
    32     for (int l, r, i = 1; i <= T; i++)
    33     {
    34         scanf("%d%d", &l, &r);
    35         query[i] = {i, l, r, l / blockSize, 0LL};
    36     }
    37     std::sort(query + 1, query + T + 1);
    38 }
    39 
    40 inline void add(int pos)
    41 {
    42     int &c = C[A[pos]];
    43     curAns += (2LL * c + 1) * A[pos];
    44     c += 1;
    45 }
    46 inline void subtract(int pos)
    47 {
    48     int &c = C[A[pos]];
    49     curAns -= (2LL * c - 1) * A[pos];
    50     c -= 1;
    51 }
    52 
    53 void process()
    54 {
    55     int left = 0, right = 0;
    56     for (int i = 1; i <= T; i++)
    57     {
    58         while (left < query[i].left)
    59             subtract(left++);
    60         while (left > query[i].left)
    61             add(--left);
    62         while (right < query[i].right)
    63             add(++right);
    64         while (right > query[i].right)
    65             subtract(right--);
    66 
    67         query[i].ans = curAns;
    68     }
    69 }
    70 
    71 void solve()
    72 {
    73     process();
    74     std::sort(query + 1, query + T + 1, [] (const Query& A, const Query& B) {
    75         return A.id < B.id;
    76     });
    77     for (int i = 1; i <= T; i++)
    78         printf("%lld
    ", query[i].ans);
    79 }
    80 
    81 int main()
    82 {
    83     input();
    84     solve();
    85     return 0;
    86 }
  • 相关阅读:
    requests使用text可以查看源码
    正则表达式之search、sub
    【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法
    php:对象(object)数据类型实例详解
    usage: git remote add [<options>] <name> <url> -f, --fetch fetch the remote branches --tags import all tags and associated objects when fetching
    PHP 可选参数
    php中文乱码问题的终极解决方案汇总
    html表单提交给PHP然后浏览器显示出了PHP的源代码
    wamp 安装
    wamp选择语言
  • 原文地址:https://www.cnblogs.com/Onlynagesha/p/8797262.html
Copyright © 2011-2022 走看看