[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 10005
using 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;
} 

 

posted @ 2017-05-21 10:46  Zars19  阅读(174)  评论(0编辑  收藏  举报