Evanyou Blog 彩带

BZOJ2120/洛谷P1903 [国家集训队] 数颜色 [带修改莫队]

  BZOJ传送门洛谷传送门

数颜色

题目描述

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

 

输入输出样例

输入样例#1: 复制
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
输出样例#1: 复制
4
4
3
4

  分析:

  一开始不会打带修改莫队,就直接打了个不带分块的普通莫队,然后在洛谷水了40分,然后看了某位大佬的博客以后,会了带修改莫队,结果被洛谷数据卡常卡了一个小时,这数据也太可怕了吧。。。给出数据的人跪了Orz。。。(BZOJ上的数据一遍就过了。。。)把能用的优化都丢进去了,然后8000+ms过的。。。如果不会带修改莫队,请参考这位大佬的博客。这里蒟蒻就只放代码了。

  Code:

 

#include<bits/stdc++.h>
#define swap(x,y) x^=y,y^=x,x^=y
using namespace std;
const int N=5e4+7;
const int M=1e6+7;
int n,m,s,L,R,tot,ans[N];
int a[N],c[M],rn,qn;
struct Node{
    int x,y,id,pos;
    friend bool operator < (const Node a,const Node b){
        if((a.x-1)/s!=(b.x-1)/s)return ((a.x-1)/s)<((b.x-1)/s);
        if((a.y-1)/s!=(b.y-1)/s)return ((a.y-1)/s)<((b.y-1)/s);
        return a.id<b.id;
    }
}Q[N];
struct Num{
int x,y;}C[N];
char obuf[1<<24], *O=obuf;
inline int read()
{
    char ch=getchar();int num=0;
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9'){
    num=num*10+ch-'0';ch=getchar();}
    return num;
}
inline void print(int x)
{
    if(x>9)print(x/10);
    *O++ = x%10+'0'; 
}
inline void change(int x,int i)
{
    if(Q[i].x<=C[x].x&&C[x].x<=Q[i].y){
        if(--c[a[C[x].x]]==0)tot--;
        if(++c[C[x].y]==1)tot++; }
    swap(a[C[x].x],C[x].y);
}
inline void add(int x)
{if(++c[a[x]]==1)tot++;}
inline void del(int x)
{if(--c[a[x]]==0)tot--;}
inline void work()
{
    sort(Q+1,Q+qn+1);int now=0;
    for(int i=1;i<=qn;i++){
        while(L<Q[i].x)del(L++);
        while(L>Q[i].x)add(--L);
        while(R<Q[i].y)add(++R);
        while(R>Q[i].y)del(R--);
        while(now<Q[i].id){change(++now,i);}
        while(now>Q[i].id){change(now--,i);}
        ans[Q[i].pos]=tot;}
    for(int i=1;i<=qn;i++)
    {print(ans[i]);*O++ = '\n';}
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=m;i++){
    char ch[5];scanf("%s",ch);
    int x=read();int y=read();
    if(ch[0]=='R'){C[++rn].x=x;C[rn].y=y;}
    else {Q[++qn].x=x;Q[qn].y=y;
    Q[qn].id=rn;Q[qn].pos=qn;}}
    s=ceil(exp((log(n)+log(qn))/3));L=1;R=0;
    work();fwrite(obuf, O-obuf, 1, stdout);
    return 0;
}

 

 

 

 

posted @ 2018-05-31 21:05  HolseLee  阅读(169)  评论(0编辑  收藏  举报