数颜色(带修莫队模板)

Posted hsez-cyx

tags:

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

数颜色(luogu)

Description

题目描述

墨墨购买了一套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支画笔中共有几种不同颜色的画笔。

Solution

带修莫队模板(加一重排序元素:时间)

注意:每个时间点修改前 值可能不一样!!!卡了我一下午。。。

另外记得一定要吸氧

Code

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=1e6+10;
int n,m,T[N][3],a[N],nt,nl,nr,s[N],si,cnt,ans[N],an,tot;
char ch[5];
struct node
{
    int l,r,t,id;
    bool operator <(const node &o)const
    {
        return l/si==o.l/si?(r/si==o.r/si?t<o.t:r<o.r):l<o.l;
    }
}q[N];
void get(int x,int d)
{
    s[x]+=d;
    if(d<0) an-=s[x]==0;
    if(d>0) an+=s[x]==1;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=0;i<m;i++)
    {
        scanf("%s",ch);
        if(ch[0]==Q)
        {
            scanf("%d%d",&q[tot].l,&q[tot].r);
            q[tot].t=cnt,q[tot].id=tot,tot++;
        }
        else
        {
            ++cnt,scanf("%d%d",&T[cnt][0],&T[cnt][2]);
            T[cnt][1]=a[T[cnt][0]];
            a[T[cnt][0]]=T[cnt][2];
        }
    }
    for(int i=cnt;i;i--) a[T[i][0]]=T[i][1];
    si=ceil(exp((log(n)+log(cnt))/3));
    sort(q,q+tot);
    for(int i=0;i<tot;i++)
    {
        while(q[i].l<nl) an+=!s[a[--nl]]++;
        while(q[i].l>nl) an-=!--s[a[nl++]];
        while(q[i].r>nr) an+=!s[a[++nr]]++;
        while(q[i].r<nr) an-=!--s[a[nr--]];
        while(q[i].t<nt)
        {
            int wz=T[nt][0];
            if(nl<=wz && wz<=nr) an-=!--s[a[wz]];
            a[wz]=T[nt--][1];
            if(nl<=wz && wz<=nr) an+=!s[a[wz]]++;
        };
        while(q[i].t>nt)
        {
            int wz=T[++nt][0];
            if(nl<=wz && wz<=nr) an-=!--s[a[wz]];
            a[wz]=T[nt][2];
            if(nl<=wz && wz<=nr) an+=!s[a[wz]]++;
        };
        ans[q[i].id]=an;
    }
    for(int i=0;i<tot;i++)
        printf("%d
",ans[i]);
    return 0;
}

 

以上是关于数颜色(带修莫队模板)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2120 数颜色 (带修莫队)

2120: 数颜色(带修莫队)

Luogu1903数颜色(带修莫队)

数颜色 / 维护队列(带修莫队板子)

bzoj2120 数颜色——带修莫队

[带修莫队] Bzoj 2120 数颜色