• 【细节题 离线 树状数组】luoguP4919 Marisa采蘑菇


    歧义差评;但是和题意理解一样了之后细节依然处理了很久,说明还是水平不够……

    题目描述

    Marisa来到了森林之中,看到了一排nn个五颜六色的蘑菇,编号从1-n1−n,这些蘑菇的颜色分别为col[1],col[2]...col[n]col[1],col[2]...col[n]由于她很挑剔,所以她只会采那些"魔法蘑菇"

    一个蘑菇被叫做"魔法蘑菇",当且仅当它在给定的某段区间内,并且在这段给定区间内与它颜色相同的蘑菇(包括它本身)的个数 与在这个给定区间外这种颜色的蘑菇的个数之差小于等于常数kk

    现在Marisa会做出mm个询问,每次询问你[l,r][l,r]中有多少种不同颜色的"魔法蘑菇"

    输入输出格式

    输入格式:

    第一行三个整数n,m,kn,m,k
    第二行nn个正整数,表示蘑菇的颜色col[i]col[i]
    之后mm行,每行两个正整数l,rl,r,表示Marisa询问的区间的左端点和右端点,数据保证0<l≤r≤n0<l≤r≤n

    输出格式:

    共mm行,每行一个整数xx,表示询问区间中不同颜色的"魔法蘑菇"的数量


    题目分析

    这是一类经典的区间问题。形如mex和HH的项链。 

    区别在于对于每一个点来说,合法区间是$l[i],r[i]$————那么就是预处理的细节要多加小心。其他操作都是大同小异的。

     1 #include<bits/stdc++.h>
     2 const int maxn = 2000035;
     3 
     4 struct QRs
     5 {
     6     int l,r,id;
     7     bool operator < (QRs a) const
     8     {
     9         return l < a.l;
    10     }
    11 }q[maxn];
    12 int n,m,k,now;
    13 std::vector<int> w[maxn];
    14 int a[maxn],t[maxn],f[maxn],v[maxn];
    15 int st[maxn],pre[maxn],nxt[maxn],ans[maxn];
    16 
    17 int read()
    18 {
    19     char ch = getchar();
    20     int num = 0;
    21     bool fl = 0;
    22     for (; !isdigit(ch); ch=getchar())
    23         if (ch=='-') fl = 1;
    24     for (; isdigit(ch); ch=getchar())
    25         num = (num<<1)+(num<<3)+ch-48;
    26     if (fl) num = -num;
    27     return num;
    28 }
    29 int lowbit(int x){return x&-x;}
    30 void add(int x, int c)
    31 {
    32     if (!x) return;
    33     for (; x<=n; x+=lowbit(x)) f[x] += c;
    34 }
    35 int query(int x)
    36 {
    37     int ret = 0;
    38     for (; x; x-=lowbit(x)) ret += f[x];
    39     return ret;
    40 }
    41 void update(int x, int c)
    42 {
    43     add(st[x], c), add(nxt[x], -c);
    44 }
    45 int main()
    46 {
    47     n = read(), m = read(), k = read();
    48     for (int i=1; i<=n; i++)
    49         a[i] = read(), v[i] = ++t[a[i]], w[a[i]].push_back(i);
    50     for (int i=1; i<=n; i++)
    51     {
    52         int lft = (t[a[i]]+k)/2, rgt = (t[a[i]]-k+1)/2;
    53         if (v[i]+lft-1 < t[a[i]]){
    54             if (v[i]+lft-1 >= 0) nxt[i] = w[a[i]][v[i]+lft-1];
    55             else nxt[i] = i;
    56         }
    57         else nxt[i] = n+1;
    58         if (rgt >= 1&&v[i]+rgt-2 >= 0){
    59             if (v[i]+rgt-2 < t[a[i]]) st[i] = w[a[i]][v[i]+rgt-2];
    60             else st[i] = n+1;
    61         }
    62         else st[i] = i;
    63         if (v[i] < t[a[i]])
    64             pre[i] = w[a[i]][v[i]];
    65         else pre[i] = n+1;
    66     }
    67     for (int i=1; i<=n; i++)
    68         if (t[a[i]]){
    69             update(i, 1);
    70             t[a[i]] = 0;
    71         }
    72     for (int i=1; i<=m; i++)
    73         q[i].l = read(), q[i].r = read(), q[i].id = i;
    74     std::sort(q+1, q+m+1);
    75     for (int i=1; i<=m; i++)
    76     {
    77         for (; now < q[i].l; now++)
    78             update(now, -1), update(pre[now], 1);
    79         ans[q[i].id] = query(q[i].r)-query(q[i].l-1);
    80     }
    81     for (int i=1; i<=m; i++) printf("%d
    ",ans[i]);
    82     return 0;
    83 }

    END

  • 相关阅读:
    NYOJ458
    NYOJ67
    NYOJ105
    NYOJ1071
    NYOJ463
    C语言练字用小软件 — Practise_Calligraphy_1.0(ANSI)
    NYOJ276
    NYOJ455
    NYOJ74
    Jzoj4458 密钥破解——Pollard-rho
  • 原文地址:https://www.cnblogs.com/antiquality/p/9769428.html
Copyright © 2020-2023  润新知