[bzoj2120] [洛谷P1903] 数颜色

Description

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

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

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

Sample Input

6 5

1 2 3 4 5 5

Q 1 4

Q 2 6

R 1 2

Q 1 4

Q 2 6

Sample Output

4

4

3

4

HINT

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。


想法

带修改莫队。

与普通莫队其实一个意思,就是多了一个tim表示在这个询问操作时已进行了几次修改。

进行一些修改操作使当前状态与这个询问时原本的状态相同。


代码

注意细节!!!

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>

using namespace std;

const int N = 10005;

int block;
int bl(int x) { return (x-1)/block+1; }

int cnt1,cnt2;
struct ask{
    int l,r,id,tim;
    bool operator < (const ask &b) const{
        return bl(l)<bl(b.l) || (bl(l)==bl(b.l) && r<b.r);
    }
}q[N];
struct cg{
    int x,fr,to;
}d[N];

int a[N],cnt[1000005];
int cur,L,R;
void add(int x){
    cnt[a[x]]++;
    if(cnt[a[x]]==1) cur++;
}
void del(int x){
    cnt[a[x]]--;
    if(cnt[a[x]]==0) cur--;
}

void cg_add(int x){
    int id=d[x].x;
    if(L<=id && id<=R){ // 注意是id(即d[x].x)啊,并不是x
        del(id);
        a[id]=d[x].to;
        add(id);
    }
    else a[id]=d[x].to;
}
void cg_del(int x){
    int id=d[x].x;
    if(L<=id && id<=R){
        del(id);
        a[id]=d[x].fr;
        add(id);
    }
    else a[id]=d[x].fr;
}

int n,m;
int ans[N];

int main()
{
    char opt[1];
    int x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=m;i++){
        scanf("%s",opt);
        scanf("%d%d",&x,&y);
        if(opt[0]==‘Q‘){
            cnt1++;
            q[cnt1]=(ask){x,y,cnt1,cnt2};
        }
        else{
            cnt2++;
            d[cnt2]=(cg){x,a[x],y};
            a[x]=y;
        }
    }
    block=sqrt(n);
    sort(q+1,q+cnt1+1);

    int t=cnt2;
    L=R=1;
    cnt[a[1]]++; cur=1;
    for(int i=1;i<=cnt1;i++){
        while(R<q[i].r) add(++R);
        while(L>q[i].l) add(--L);
        while(R>q[i].r) del(R--);
        while(L<q[i].l) del(L++);
        while(t>q[i].tim) cg_del(t--); //注意顺序!!
        while(t<q[i].tim) cg_add(++t);
        ans[q[i].id]=cur;
    }
    for(int i=1;i<=cnt1;i++) printf("%d\n",ans[i]);

    return 0;
}

原文地址:https://www.cnblogs.com/lindalee/p/8481390.html

时间: 2024-11-09 06:45:09

[bzoj2120] [洛谷P1903] 数颜色的相关文章

洛谷 P1028 数的计算

题目描述 我们要求找出具有下列性质数的个数(包含输入的自然数n): 先输入一个自然数n(n<=1000),然后对此自然数按照如下方法进行处理: 1.不作任何处理; 2.在它的左边加上一个自然数,但该自然数不能超过原数的一半; 3.加上数后,继续按此规则进行处理,直到不能再加自然数为止. 输入输出格式 输入格式: 一个自然数n(n<=1000) 输出格式: 一个整数,表示具有该性质数的个数. 输入输出样例 输入样例#1: 6 输出样例#1: 6 说明 满足条件的数为 6,16,26,126,36

[NOIP2001] 提高组 洛谷P1025 数的划分

题目描述 将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. 输入输出格式 输入格式: n,k (6<n<=200,2<=k<=6) 输出格式: 一个整数,即不同的分法. 输入输出样例 输入样例#1: 7 3 输出样例#1: 4 说明 四种分法为:1,1,5;1,2,4;1,3,3;2,2,3; 暴搜. 可以加一点剪枝,比如说当剩余数不够均分成剩余

洛谷-拼数-NOIP1998提高组复赛

题目描述 Description 设有n个正整数(n≤20),将它们联接成一排,组成一个最大的多位整数. 例如:n=3时,3个整数13,312,343联接成的最大整数为:34331213 又如:n=4时,4个整数7,13,4,246联接成的最大整数为:7424613 输入输出格式 Input/output 输入格式: 第一行,一个正整数n. 第二行,n个正整数. 输出格式: 一个正整数,表示最大的整数 输入输出样例 Sample input/output 样例测试点#1 输入样例: 313131

洛谷——P1255 数楼梯

题目描述 楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶. 编一个程序,计算共有多少种不同的走法. 输入输出格式 输入格式: 一个数字,楼梯数. 输出格式: 走的方式几种. 输入输出样例 输入样例#1: 4 输出样例#1: 5 说明 用递归会太慢,需用递推 (60% N<=50 ,100% N<=5000) 也是曾经做过的一道题,单纯复习一下高精斐波那契模板 #include<cstdio> #include<cstdlib> #include<cstring&

洛谷-牛数-野题

题目描述 Description 我们下面来研究整数性质,我们知道质数只有 1和自身两个因子,合数至少有除了 1和自身的其他因子,我们也知道“猫老大数”是只能分解成两个质数乘积形式的数,那么能分解成两个合数的数呢?我们称之为“牛数”.下面编程判断整数是否为“牛数”. 输入输出格式 Input/output 输入格式:第一行为 t(1<=t<=100),表示测试数据组数. 接下来 t行,每行一个正整数x(1<=x<=10^9)输出格式: 对于每个输入数据 x,判断它是否为“牛数”,并

洛谷 P1255 数楼梯 高精度加法

P1255 数楼梯 时空限制1s / 128MB 题目描述 楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶. 编一个程序,计算共有多少种不同的走法. 输入输出格式 输入格式: 一个数字,楼梯数. 输出格式: 走的方式几种. 输入输出样例 输入样例#1: 4 输出样例#1: 5 说明 用递归会太慢,需用递推 (60% N<=50 ,100% N<=5000) --------------------------------------------------------------------

洛谷 P2646 数数zzy

P2646 数数zzy 题目描述 zzy自从数学考试连续跪掉之后,上数学课就从来不认真听了(事实上他以前也不认真听).于是他开始在草稿纸上写写画画,比如写一串奇怪的字符串.然后他决定理♂性♂愉♂悦♂一下:统计这串字符串当中共有多少个为“zzy”的子序列(注意是子序列而非子串).但是由于他写的字符串实在是太长啦,而且他是个超级大蒟蒻,根本就数不过来.所以他决定请求你这个超级大神犇的帮助.你可以帮帮他吗? 输入输出格式 输入格式: 一行仅含小写字母的字符串. 输出格式: 一行,一个非负整数,表示输入

洛谷 P1255 数楼梯

P1255 数楼梯 题目描述 楼梯有N阶,上楼可以一步上一阶,也可以一步上二阶. 编一个程序,计算共有多少种不同的走法. 输入输出格式 输入格式: 一个数字,楼梯数. 输出格式: 走的方式几种. 输入输出样例 输入样例#1: 复制 4 输出样例#1: 复制 5 说明 用递归会太慢,需用递推 (60% N<=50 ,100% N<=5000) 思路:数学+高精 #include<cstdio> #include<cstring> #include<iostream&

洛谷 P1025 数的划分

P1025 数的划分 题目描述 将整数n分成k份,且每份不能为空,任意两个方案不相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. 输入输出格式 输入格式: n,k (6<n<=200,2<=k<=6) 输出格式: 一个整数,即不同的分法. 输入输出样例 输入样例#1: 复制 7 3 输出样例#1: 复制 4 说明 四种分法为:1,1,5;1,2,4;1,3,3;2,2,3; 思路:数据范围很小