题目描述

墨墨购买了一套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. Python字符串格式化方式之format

    format方式是在Python3引入了一个新的字符串格式化的方法,并且随后支持了Python2.7.这个新的字符串格式化方法摆脱了%操作符并且使得字符串格式化的语法更规范了.现在时候通过调用字符串对 ...

  2. min-25筛学习笔记

    Min_25筛简介 \(\text{min_25}\)筛是一种处理一类积性函数前缀和的算法. 其中这类函数\(f(x)\)要满足\(\sum_{i=1}^{n}[i\in prime]\cdot f( ...

  3. ASP.NET面试题130道

     130道ASP.NET面试题 1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. ...

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

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

  5. dicker第三章--网络管理

  6. 5.安装CentOS后,开机找不到Win10的启动选项解决办法

    现象:在Win10下安装了CentOS7双系统,开机后,居然发现找不到Win10启动选项,默认进入了CentOS系统. 解决办法: 方法一:笔者一般是用创建一个Win10启动盘,电脑重启进入启动盘后, ...

  7. Python定义点击右上角关闭按钮事件

    Python定义点击右上角关闭按钮事件(Python defines the event of clicking the close button in the upper right corner) ...

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

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

  9. 迷你商城后台管理系统————stage1需求分析

    PS:迷你商城后台管理系统---需求分析.docx下载~click me 迷你商城后台管理系统-- 需求分析 1. 引言 作为互联网热潮的崛起,消费者们的普遍差异化,实体商城要想在互联网的浪潮中继续发 ...

  10. Linux/Windows下安装SonarCube

    1. 下载合适的版本,尽量不要下载最新的版本,最新的版本要求Java 11+,如果没有安装最新版的Java的话,尽量用 SonarQube 7.0 以下的版本,SonarQube 7.0是可以用jdk ...