P1903 [国家集训队]数颜色 (带修改莫队)
题目描述
墨墨购买了一套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支画笔中共有几种不同颜色的画笔。
输入输出样例
说明
对于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 [国家集训队]数颜色 (带修改莫队)的更多相关文章
- BZOJ2120/洛谷P1903 [国家集训队] 数颜色 [带修改莫队]
BZOJ传送门:洛谷传送门 数颜色 题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R ...
- P1903 [国家集训队]数颜色 带修改莫队板子
大概就是要多加一维time 然后按照(l的块,r的块,time)为关键字排序 转移区间修改还是按照莫队的方式(每个修改要记修改前后的状态) 然后玄学dalao告诉窝块大小设为\(O(n^{\frac{ ...
- bzoj 2120 数颜色 带修改莫队
带修改莫队,每次查询前调整修改 #include<cstdio> #include<iostream> #include<cstring> #include< ...
- BZOJ2120数颜色(带修改莫队)
莫队算法是一种数据结构的根号复杂度替代品,主要应用在询问[l,r]到询问[l+1,r]和[l,r+1]这两个插入和删除操作复杂度都较低的情况下.具体思想是:如果把一个询问[l,r]看做平面上的点(l, ...
- [国家集训队][bzoj2120] 数颜色 [带修改莫队]
题面: 传送门 思路: 这道题和SDOI2009的HH的项链很像,只是多了一个修改 模板套上去呀 莫队学习请戳这里:莫队 Code: #include<iostream> #include ...
- COGS.1901.[模板][国家集训队2011]数颜色(带修改莫队)
题目链接 COGS BZOJ2120 洛谷P1903 /* Add和Subd函数中的vis不能直接设为=1或=0 比如 l=1,r=0 -> l=3,r=5 时,[1,5]的vis标记全都是1 ...
- bzoj2120 / P1903 [国家集训队]数颜色 / 维护队列(带修改莫队)
P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队 在原有指针$(l,r)$上又添加了时间指针$t$ 贴一段dalao的解释 带修改的莫队,和原版莫队相比,多了一个时间轴 原版莫队是将区间( ...
- 洛谷 P1903 [国家集训队]数颜色 解题报告
P1903 [国家集训队]数颜色 题目描述 墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1.Q L R代表询问你从第\(L\) ...
- P1903 [国家集训队]数颜色 / 维护队列 带修改莫队
题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...
随机推荐
- Jmeter 接口测试之MD5加密函数(函数助手篇)
转自:https://blog.csdn.net/hhyangel372/article/details/81571058 本文给大家介绍一下如何使用Jmeter自带的函数对常量和变量进行简单的加密处 ...
- python day7: time,datetime,sys,pickle,json模块
目录 python day 7 1. time模块 2. datetime模块 2.1 date类 2.2 time类 2.3 datetime类 2.4 timedelta类 2.5 tzinfo时 ...
- AndroidStudio中Run按钮是灰色的解决方法
在model下拉框中选择app.如果下拉框中没有app,(没有工程名),那么请先去设置: Android Studio 3.3.0 File->sync project with gradles ...
- hadoop完整集群遇到问题汇总
1> 设置静态ip: 由于虚拟机在重启之后ip会再次重置,为了后续的麻烦我吗可以设置成静态ip的方式: cd /etc/sysconfig/network-scripts/ 修改对比如下: ...
- js 判断数组中是否包含某个元素(转载)
来源:https://www.cnblogs.com/yunshangwuyou/p/10539090.html 方法一:array.indexOf(item,start):元素在数组中的位置,如果没 ...
- python Linux 环境 (版本隔离工具)
python Linux 环境 (版本隔离工具) 首先新建用户,养成良好习惯useradd python 1.安装pyenv GitHub官网:https://github.com/pyenv/pye ...
- Android笔记(六十六) android中的动画——XML文件定义属性动画
除了直接在java代码中定义动画之外,还可以使用xml文件定义动画,以便重用. 如果想要使用XML来编写动画,首先要在res目录下面新建一个animator文件夹,所有属性动画的XML文件都应该存放在 ...
- gitlab及jenkins
1.安装配置gitlab服务,在gitlab新建一个仓库,配置本地密钥,并通过ssh方式拉取gitlab仓库代码 https://packages.gitlab.com/gitlab/gitlab-c ...
- 使用Junit测试框架学习Java
前言 在日常的开发中,离不开单元测试,而且在学习Java时,特别是在测试不同API使用时要不停的写main方法,显得很繁琐,所以这里介绍使用Junit学习Java的方法.此外,我使用log4j将结果输 ...
- 使用maven导入module时,报java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
在新装IDEA导入Flink源码时出现一些问题,在此记录,希望能帮到大伙! 一.环境 IDEA2019.1.2(破解版):OpenJDK 1.8.0_40:Maven 3.5.3/3.2.5/3.6. ...