zoukankan      html  css  js  c++  java
  • P2709 小B的询问 【普通莫队】

    这是我的莫队入门题,我也了解到了莫队分为普通莫队以及带修莫队。顾名思义,普通莫队不需要修改区间的值,而带修莫队处理区间的值会修改的查询。

    能用莫队的前提条件

    1.在知道 【l, r】中信息时,可以在 O(1)的复杂度内知道 【l - 1, r】,【l + 1, r】,【l, r - 1】,【l, r + 1】的信息,否则复杂度会爆炸。

    2.能离线处理。

    莫队的时间复杂度为O(n ^ 1.5),但实际效果一定会优于这个时间复杂度。

    莫队的主要操作:

    1.对查询区间,以 left 来进行分块,然后将分块作为第一关键字来进行从小到大的排序,以right为第二关键字来进行从小到大的排序

    2.找到区间之间的转移方程,边查询边修改。

    题目链接:https://www.luogu.org/problemnew/show/P2709

    思路:

    1.莫队的模板题。

    2.值得注意的是扩充区间时,先动指针,再修改值。缩小区间时,先修改值,再动指针。这样做是为了保证区间一定有长度。

    代码如下:

     1 #include<stdio.h>
     2 #include<algorithm>
     3 #include<math.h>
     4 #include<string.h>
     5 #define mem(a, b) memset(a, b, sizeof(a))
     6 using namespace std;
     7 
     8 int n, m, k;
     9 int num[50010];
    10 long long cnt[50010];
    11 long long ANS[50010];
    12 
    13 struct Query
    14 {
    15     int l, r, id;
    16     int pos;
    17 }q[50010];
    18 
    19 bool cmp(Query a, Query b)
    20 {
    21     if(a.pos != b.pos)
    22         return a.pos < b.pos; //第1关键字是块 
    23     else
    24         return a.r < b.r;  //第2关键字是右边界 
    25 }
    26 
    27 int main()
    28 {
    29     scanf("%d%d%d", &n, &m, &k);
    30     mem(cnt, 0);
    31     for(int i = 1; i <= n; i ++)
    32         scanf("%d", &num[i]);
    33     int fk = sqrt(n);
    34     for(int i = 1; i <= m; i ++)  //莫队要离线处理
    35     {
    36         scanf("%d%d", &q[i].l, &q[i].r);
    37         q[i].id = i;
    38         q[i].pos = (q[i].l - 1) / fk + 1;
    39     }
    40     sort(q + 1, q + 1 + m, cmp);
    41     int L = 1, R = 0;
    42     long long ans = 0;
    43     for(int i = 1; i <= m; i ++)
    44     {
    45         while(L > q[i].l)//扩充 
    46         {
    47             L --;
    48             cnt[num[L]] ++;
    49             ans += 2 * cnt[num[L]] - 1;
    50         }
    51         while(R < q[i].r) //扩充
    52         {
    53             R ++;
    54             cnt[num[R]] ++;
    55             ans += 2 * cnt[num[R]] - 1;
    56         }
    57         while(L < q[i].l)//缩小 
    58         {
    59             cnt[num[L]] --;
    60             ans -= 2 * cnt[num[L]] + 1;
    61             L ++;
    62         }
    63         while(R > q[i].r)//缩小 
    64         {
    65             cnt[num[R]] --;
    66             ans -= 2 * cnt[num[R]] + 1;
    67             R --;
    68         }
    69         ANS[q[i].id] = ans;
    70     }
    71     for(int i = 1; i <= m; i ++)
    72     {
    73         printf("%lld
    ", ANS[i]);
    74     }
    75     return 0;
    76 }
    View Code
  • 相关阅读:
    简单字典操作
    字符串操作
    2017年10月7日
    循环列表练习
    Zabbix4.0系统告警"Zabbix agent on Zabbix server is unreachable for 5 minutes"
    Zabbix4.0系统告警“Zabbix server is not running”
    FreeRADIUS使用了在Cisco IOS配置示例的管理访问
    Cisco AAA Configuration
    使用工具Csvde导出域中所有用户信息
    McAfee Agent卸载方法
  • 原文地址:https://www.cnblogs.com/yuanweidao/p/10986682.html
Copyright © 2011-2022 走看看