首页 > 代码库 > [BZOJ 2120]数颜色(带修改莫队)

[BZOJ 2120]数颜色(带修改莫队)

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Solution

看别人的代码学习了带修改的莫队

对于每个询问记录一个修改到的时间点,按[l所在的块,r所在的块,修改时间]排序

暴力处理就好啦…

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#define MAXN 10005using namespace std;int n,m,block,col[MAXN];int vis[MAXN*100],num[MAXN*100],last[MAXN],tot=0,cnt=0,ans=0,res[MAXN];int read(){    int x=0,f=1;char c=getchar();    while(c<0||c>9){        if(c==-)f=-1;c=getchar();    }    while(c>=0&&c<=9){        x=(x<<1)+(x<<3)+c-0;c=getchar();    }    return x*f;}struct Node1{    int pos,c,pre;    Node1(int pos=0,int c=0,int pre=0):pos(pos),c(c),pre(pre){}}modify[1005];struct Node2{    int l,r,now,id;    Node2(int l=0,int r=0,int now=0,int id=0):l(l),r(r),now(now),id(id){}    bool operator < (const Node2 x) const    {        if((l-1)/block==(x.l-1)/block)        {            if((r-1)/block==(x.r-1)/block)            return now<x.now;            else return (r-1)/block<(x.r-1)/block;        }        else return (l-1)/block<(x.l-1)/block;     }}query[MAXN];void work(int pos){    if(vis[pos])    {        --num[col[pos]];        if(!num[col[pos]])ans--;    }    else     {        if(!num[col[pos]])ans++;        ++num[col[pos]];    }    vis[pos]^=1;}int main(){    n=read(),m=read();    block=sqrt(n+0.1);    for(int i=1;i<=n;i++)    col[i]=read(),last[i]=col[i];    for(int i=1;i<=m;i++)    {        char opt=getchar();        while(opt!=Q&&opt!=R)opt=getchar();        int x=read(),y=read();        if(opt==Q)        {++cnt,query[cnt]=Node2(x,y,tot,cnt);}        else         {            modify[++tot]=Node1(x,y,last[x]);            last[x]=y;        }    }    sort(query+1,query+1+cnt);    int l,r;    l=r=1,work(1);    for(int i=1;i<=cnt;i++)    {        for(int j=query[i-1].now+1;j<=query[i].now;j++)        {            if(vis[modify[j].pos])            {                work(modify[j].pos);                col[modify[j].pos]=modify[j].c;                work(modify[j].pos);            }            else col[modify[j].pos]=modify[j].c;        }        for(int j=query[i-1].now;j>query[i].now;j--)        {            if(vis[modify[j].pos])            {                work(modify[j].pos);                col[modify[j].pos]=modify[j].pre;                work(modify[j].pos);            }            else col[modify[j].pos]=modify[j].pre;        }        while(l<query[i].l)work(l++);        while(l>query[i].l)work(--l);        while(r>query[i].r)work(r--);        while(r<query[i].r)work(++r);        res[query[i].id]=ans;    }    for(int i=1;i<=cnt;i++)    printf("%d\n",res[i]);    return 0;} 

 

[BZOJ 2120]数颜色(带修改莫队)