题目描述

墨墨购买了一套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

说明

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

来源:bzoj2120

 //感谢xxy dalao的指导, 虽然不得不看了blog才A了这道题。。。。 

 //但是为什么他们一个 dfs 10+ ms就过,我却跑了100+ ?。。。。。 

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std; const int N=1e4+;
const int M=1e6+; int n,m;
int a[N];
int ans;
int belong[N];
int c[M];
int query_cnt,modify_cnt;
struct Query //询问操作
{
int ans; //这次询问的答案
int l,r; //这次询问的左右区间
int tim; //这是第几次询问,便于最后将询问排序输出ans
int tim_modify; //记录这次询问是在第几次修改之后的,便于修改和撤销
}query[N];
struct Modify //修改操作
{
int tim; //这是第几次修改操作
int pos,col,pre_col; //修改的位置、修改之前的颜色、修改之后的颜色
}modify[N]; int read()
{
char c=getchar();int num=;
for(;!isdigit(c);c=getchar())
if(c=='Q')
return ;
else if(c=='R')
return ;
for(;isdigit(c);c=getchar())
num=num*+c-'';
return num;
} bool cmp1(const Query &a,const Query &b) //将询问操作排序
{
if(belong[a.l]==belong[b.l]) //为了保证效率,按照三个关键字排序,前两个和普通的不带修改的莫队一样,第三个关键字是修改时间
if(belong[a.r]==belong[b.r])
return a.tim_modify<b.tim_modify;
else
return belong[a.r]<belong[b.r];
return belong[a.l]<belong[b.l];
} bool cmp2(const Query &a,const Query &b) //将query按照询问时间排序,便于输出ans
{
return a.tim<b.tim;
} int main()
{
n=read(),m=read();
int size=sqrt(n);
for(int i=;i<=n;++i)
a[i]=read(),belong[i]=(i-)/size+;
for(int i=,type;i<=m;++i)
{
type=read();
if(type==)
{
++query_cnt;
query[query_cnt].l=read();
query[query_cnt].r=read();
query[query_cnt].tim=query_cnt; //记录这是第几次询问
query[query_cnt].tim_modify=modify_cnt; //记录当前询问是在第几次修改之后
}
else
{
++modify_cnt;
modify[modify_cnt].pos=read();
modify[modify_cnt].col=read(); //修改之后的值
modify[modify_cnt].tim=modify_cnt;
modify[modify_cnt].pre_col=a[modify[modify_cnt].pos]; //记录修改之前的值
a[modify[modify_cnt].pos]=modify[modify_cnt].col; //修改
}
}
for(int i=modify_cnt;i;--i) //把修改了的a数组还原回去
a[modify[i].pos]=modify[i].pre_col;
sort(query+,query+query_cnt+,cmp1);
int now_modify=,l=,r=;
for(int i=;i<=query_cnt;++i) //当时被卡在了修改和撤销上,没理解透彻,不知道该不该更新ans,因为当时觉得如果更新了ans的话会让后边在移动左右端点更新值得时候重复,其实不然,因为如果当前修改的值在当前询问的区间中,那么它是不会被更改的(因为改到左右端点的时候就停止了,不会来改它),如果不在当前询问的区间内,那么在移动端点的时候,被+1的ans会被还原回去(-1),但是被-1的ans是不会变的,因为它已经没了(滑稽)
{
if(query[i].tim_modify>now_modify) //当前询问在上次修改操作之后,往后修改
{
for(int j=now_modify+;j<=query[i].tim_modify;++j)
{
if(modify[j].pos>=l&&modify[j].pos<=r) //如果修改的位置在上次询问的区间内,更新
{
--c[modify[j].pre_col];
if(!c[modify[j].pre_col])
--ans;
if(!c[modify[j].col])
++ans;
++c[modify[j].col];
}
a[modify[j].pos]=modify[j].col; //修改
}
}
if(query[i].tim_modify<now_modify) //当前询问在上次修改操作之前,撤销修改
{
for(int j=now_modify;j>query[i].tim_modify;--j)
{
if(modify[j].pos>=l&&modify[j].pos<=r)
{
--c[modify[j].col]; //把修改后的数的值还原回去
if(!c[modify[j].col])
--ans;
if(!c[modify[j].pre_col]) //被修改了的数的值还原回去
++ans;
++c[modify[j].pre_col];
}
a[modify[j].pos]=modify[j].pre_col; //撤销
}
}
if(l<query[i].l)
{
for(int j=l;j<query[i].l;++j)
{
--c[a[j]];
if(!c[a[j]])
--ans;
}
}
if(l>query[i].l)
{
for(int j=query[i].l;j<l;++j)
{
if(!c[a[j]])
++ans;
++c[a[j]];
}
}
if(r<query[i].r)
{
for(int j=r+;j<=query[i].r;++j)
{
if(!c[a[j]])
++ans;
++c[a[j]];
}
}
if(r>query[i].r)
{
for(int j=query[i].r+;j<=r;++j)
{
--c[a[j]];
if(!c[a[j]])
--ans;
}
}
l=query[i].l,r=query[i].r; //更新查询区间
query[i].ans=ans; //记录这次查询的答案
now_modify=query[i].tim_modify; //更新最新一次修改时间
}
sort(query+,query+query_cnt+,cmp2);
for(int i=;i<=query_cnt;++i)
{
printf("%d\n",query[i].ans);
}
return ;
}

P1903 [国家集训队]数颜色 (带修改莫队)的更多相关文章

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

    BZOJ传送门:洛谷传送门 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R ...

  2. P1903 [国家集训队]数颜色 带修改莫队板子

    大概就是要多加一维time 然后按照(l的块,r的块,time)为关键字排序 转移区间修改还是按照莫队的方式(每个修改要记修改前后的状态) 然后玄学dalao告诉窝块大小设为\(O(n^{\frac{ ...

  3. bzoj 2120 数颜色 带修改莫队

    带修改莫队,每次查询前调整修改 #include<cstdio> #include<iostream> #include<cstring> #include< ...

  4. BZOJ2120数颜色(带修改莫队)

    莫队算法是一种数据结构的根号复杂度替代品,主要应用在询问[l,r]到询问[l+1,r]和[l,r+1]这两个插入和删除操作复杂度都较低的情况下.具体思想是:如果把一个询问[l,r]看做平面上的点(l, ...

  5. [国家集训队][bzoj2120] 数颜色 [带修改莫队]

    题面: 传送门 思路: 这道题和SDOI2009的HH的项链很像,只是多了一个修改 模板套上去呀 莫队学习请戳这里:莫队 Code: #include<iostream> #include ...

  6. COGS.1901.[模板][国家集训队2011]数颜色(带修改莫队)

    题目链接 COGS BZOJ2120 洛谷P1903 /* Add和Subd函数中的vis不能直接设为=1或=0 比如 l=1,r=0 -> l=3,r=5 时,[1,5]的vis标记全都是1 ...

  7. bzoj2120 / P1903 [国家集训队]数颜色 / 维护队列(带修改莫队)

    P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队 在原有指针$(l,r)$上又添加了时间指针$t$ 贴一段dalao的解释 带修改的莫队,和原版莫队相比,多了一个时间轴 原版莫队是将区间( ...

  8. 洛谷 P1903 [国家集训队]数颜色 解题报告

    P1903 [国家集训队]数颜色 题目描述 墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1.Q L R代表询问你从第\(L\) ...

  9. P1903 [国家集训队]数颜色 / 维护队列 带修改莫队

    题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...

随机推荐

  1. centos7.5 离线安装ntp服务

    安装 #检查rpm包 rpm -qa | grep ntp #从https://pkgs.org/download/ntp 下载rpm包 ntp-4.2.6p5-28.el7.centos.x86_6 ...

  2. 有关Nodejs的一些插件介绍

    var child_process = require('child_process');这个可以执行cmd的命令 child_process.exec(cmdLine, function(error ...

  3. Mycat分布式数据库架构解决方案--Mycat的介绍

    echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.--这才是真正的堪称强大!!! 如果我 ...

  4. 2019年北航OO第4单元(UML)总结

    1 架构设计 经过了接近一学期的程序设计训练,在这一单元的第一次作业中我就非常注重架构的设计,竭力避免像之前一样陷入"第一次作业凑合,第二次作业重构"的不健康的迭代模式.整体上来说 ...

  5. ECSHOP(3.0.0升级3.6.0)帮助教程

    说明: 本文档只针对于未做过二开的ECSHOP3.0 用户 1.准备材料 先确保正在使用的ECShop系统版本为ecshop3.0.0并且代码没有经过二次开发,然后下载最新的ECShop3.6.0安装 ...

  6. HBase集群环境搭建v1.0

    本文档环境基于ubuntu14.04版本,如果最终不使用SuperMap iServer 9D ,可以不配置geomesa-hbase_2.11-2.0.1-bin.tar.gz (转发请注明出处:h ...

  7. IntelliJ Idea 依赖包下载成功,代码里无法import问题解决方法

    今天clone一个github上的基于maven的项目IntelliJ Idea 依赖包下载成功,代码里无法import.解决方法:删掉原来的.iml,刷新. 如果不行,可尝试:File->In ...

  8. 【转】C语言宏定义的几个坑和特殊用法

    总结一下C语言中宏的一些特殊用法和几个容易踩的坑.由于本文主要参考GCC文档,某些细节(如宏参数中的空格是否处理之类)在别的编译器可能有细微差别,请参考相应文档. 宏基础 宏仅仅是在C预处理阶段的一种 ...

  9. jQuery和bootstrap

    1. jQuery学习,搜索开发者网络: js学习: https://www.apeland.con/web/20/568 https://www.apeland.con/web/21 vue饿了么 ...

  10. React系列,初识

    学习react对于新手来说,还没有学react往往就会被webpack,npm等搞的晕头转向,所以我们今天就从最简单的方式入手 <script src="react.js"& ...