国家集训队 数颜色 - 莫队

Posted lrj124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了国家集训队 数颜色 - 莫队相关的知识,希望对你有一定的参考价值。

题目描述

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第P支画笔替换为颜色Col。

为了满足墨墨的要求,你知道你需要干什么了吗?

输入输出格式

输入格式:

 

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。

第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。

第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

 

输出格式:

 

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

 

思路

带修改莫队模板题

莫队算法详见『这里』

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200000 + 10;
int n,m,now,block,cnt[maxn],a[maxn],ans[maxn];
struct Query {
    int l,r,num;
    inline bool operator < (Query cmp) const {
        if (l/block != cmp.l/block) return l/block < cmp.l/block;
        return r < cmp.r;
    }
}q[maxn];
inline void add(int x) {
    if (x > n+1) return;
    cnt[x]++;
    if (now == x && cnt[x] > 0)
        for (int i = x;i <= n+1;i++)
            if (!cnt[i]) {
                now = i;
                break;
            }
}
inline void del(int x) {
    if (x > n+1) return;
    cnt[x]--;
    if (!cnt[x]) now = min(now,x);
}
int main() {
    scanf("%d%d",&n,&m);
    block = sqrt(n);
    a[0] = n+2;
    for (int i = 1;i <= n;i++) scanf("%d",&a[i]);
    for (int i = 1;i <= m;i++) {
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].num = i;
    }
    sort(q+1,q+m+1);
    int l = 0,r = 0;
    for (int i = 1;i <= m;i++) {
        while (l < q[i].l) del(a[l++]);
        while (l > q[i].l) add(a[--l]);
        while (r < q[i].r) add(a[++r]);
        while (r > q[i].r) del(a[r--]);
        ans[q[i].num] = now;
    }
    for (int i = 1;i <= m;i++) printf("%d\\n",ans[i]);
    return 0;
}

 

以上是关于国家集训队 数颜色 - 莫队的主要内容,如果未能解决你的问题,请参考以下文章

国家集训队 数颜色 - 莫队

[国家集训队][bzoj2120] 数颜色 [带修改莫队]

2120. [国家集训队]数颜色莫队

[莫队] 国家集训队 数颜色(尚未完成)

[国家集训队]数颜色 / 维护队列 (带修莫队模板题)

P1903 [国家集训队]数颜色 / 维护队列