国家集训队——数颜色

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第P支画笔替换为颜色Col。

题解:

做这道题之前不会带修改莫队,山神学会了之后手(嘴)把手(嘴)教我打代码。

莫队算法先放下,带修改莫队是酱的:记下所有的修改,同时为每个询问加入一个时间标记,表示这个询问发生时修改到了哪一步。求解之前记录一个时间戳。每次求解一个询问时,先按普通莫队求解,然后查看当前时间戳和这个询问的标记,不一样的话就一个时间一个时间地改过去,同时修改答案。进行时间修改时,比如这道题,swap了修改的颜色和修改前的颜色,这样可以让之后发生时间倒流。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#define MXN 10000+1
#define MXC 1000000+1
struct Query{int l,r,t,id;}q[MXN];
struct change{int p,co;}c[MXN];
int block[MXN];
bool cmp(Query A,Query B){
    if(block[A.l]==block[B.l]){
        if(A.r==B.r) return A.t<B.t;
        else return A.r<B.r;
    }
    else return block[A.l]<block[B.l];
}
int n,m,x,y;
int qsum,csum;
std::string p;
int color[MXN];
int man[MXC];
int ans[MXN];
void Change(int T,int i,int &temp){
    if(c[T].p>=q[i].l&&c[T].p<=q[i].r){
        man[color[c[T].p]]--;
        if(man[color[c[T].p]]==0) temp--;
        man[c[T].co]++;
        if(man[c[T].co]==1) temp++;
    }
    std::swap(color[c[T].p],c[T].co);
    return;
}
int main(){
    scanf("%d%d",&n,&m);
    int s=sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&color[i]);
        block[i]=i/s;
    }
    while(m--){
        std::cin>>p;
        scanf("%d%d",&x,&y);
        if(p[0]==‘Q‘){
            q[qsum].l=x;
            q[qsum].r=y;
            q[qsum].id=qsum;
            q[qsum++].t=csum;
        }
        if(p[0]==‘R‘){
            c[++csum].p=x;
            c[csum].co=y;
        }
    }
    std::sort(q,q+qsum,cmp);
    int L=0,R=0,T=0,temp=0;
    for(int i=0;i<qsum;i++){
        while(L<q[i].l){man[color[L]]--;if(man[color[L]]==0) temp--;L++;}
        while(L>q[i].l){L--;man[color[L]]++;if(man[color[L]]==1) temp++;}
        while(R<q[i].r){R++;man[color[R]]++;if(man[color[R]]==1) temp++;}
        while(R>q[i].r){man[color[R]]--;if(man[color[R]]==0) temp--;R--;}
        while(T<q[i].t){T++;Change(T,i,temp);}
        while(T>q[i].t){Change(T,i,temp);T--;}
        ans[q[i].id]=temp;
    }
    for(int i=0;i<qsum;i++) printf("%d\n",ans[i]);
    return 0;
}

代码

PS:压行严重。

原文地址:https://www.cnblogs.com/halifuda/p/8480451.html

时间: 2024-08-30 14:50:50

国家集训队——数颜色的相关文章

【[国家集训队]数颜色】

下面的同学们搞怪了 好的,话不多说,我来讲这道题时顺便就来讲讲带修莫队 不知道普通莫队是什么的请参见我之前为小Z的袜子写的博客 首先来审审题意:多个区间询问,询问[l,r]中颜色的种类数.可以单点修改颜色. 莫队可以修改??? 那么我们切入正题 这类问题被称为带修莫队(可持久化莫队). 类比到主席树,即可持久化线段树,可以引入一个"修改时间",表示当前询问是发生在前time个修改操作后的.也就是说,在进行莫队算法时,看看当前的询问和时间指针(第三个指针,别忘了s,e)是否相符,然后进行

[莫队] 国家集训队 数颜色(尚未完成)

题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col. 为了满足墨墨的要求,你知道你需要干什么了吗? 输入输出格式 输入格式: 第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数. 第2行N个整数,分别代表初始画笔排中第i支画笔的颜色. 第3行到第2+M行,每行分别代表墨墨会做的一件事

P1903 [国家集训队]数颜色 / 维护队列

毒瘤数据卡普通莫队!! 这道题跟普通的莫队题目差不多,但是多了一个修改操作. 所以带修莫队就横空出世了. 普通莫队记录左端点和右端点,那么这里就再记录一个时间轴,表示当时已经执行过几次修改. 之后莫队模板就有六个while,前四个是一样的. 最后两个判断当前修改次数和目标修改次数的关系.这个就是灵魂了. 重点看这个时间轴上的修改吧. void change(int idx, int i) { if(q[i].l <= c[idx].p && c[idx].p <= q[i].r

莫队学习总结 &amp;&amp; P1903 [国家集训队]数颜色 / 维护队列

关于时间复杂度 对于多维莫队的复杂度差不多为\(O(n^{\frac{2k-1}{k}})\) 摘自zhihu大佬 奇偶分类优化 return a.l == b.l ? (a.l & 1) ? a.r<b.r: a.r>b.r : a.l < b.l; 这样能快是因为指针移到右边后不用再跳回左边,而跳回左边后处理下一个块又要跳回右边,这样能减少一半操作,理论上能快一倍 思路 好久的题目了,之前其实只会点不修改莫队 对带修改的不大会,也就做过这一个题目 今天重新做了一边,算是有了新

cogs 1901. [国家集训队2011]数颜色

Cogs 1901. [国家集训队2011]数颜色 ★★★   输入文件:nt2011_color.in   输出文件:nt2011_color.out   简单对比时间限制:0.6 s   内存限制:512 MB [试题来源] 2011中国国家集训队命题答辩 [问题描述] 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令:1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔.2. R P Col 把第P支画笔替换为

[国家集训队2010]小Z的袜子

★★★   输入文件:hose.in   输出文件:hose.out   简单对比 时间限制:1 s   内存限制:512 MB [题目描述] 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬. 你的任务便

BZOJ 2038: [2009国家集训队]小Z的袜子(hose)

2038: [2009国家集训队]小Z的袜子(hose) Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 7676  Solved: 3509[Submit][Status][Discuss] Description 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只

BZOJ 2038: [2009国家集训队]小Z的袜子(hose) ( 莫队 )

莫队..先按sqrt(n)分块, 然后按块的顺序对询问排序, 同块就按右端点排序. 然后就按排序后的顺序暴力求解即可. 时间复杂度O(n1.5) ------------------------------------------------------------------------------ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 50009; int N,

洛谷 1775. [国家集训队2010]小Z的袜子

1775. [国家集训队2010]小Z的袜子 ★★★   输入文件:hose.in   输出文件:hose.out   简单对比时间限制:1 s   内存限制:512 MB [题目描述] 作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,