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 ...
随机推荐
- vue3 template refs dom的引用、组件的引用、获取子组件的值
介绍 通过 ref() 还可以引用页面上的元素或组件. DOM 的引用 <template> <div> <h3 ref="h3Ref">Tem ...
- 微信公众号 分享接口 签名通过 分享无效果(JSSDK自定义分享接口的策略调整)
为规范自定义分享链接功能在网页上的使用,自2017年4月25日起,JSSDK“分享到朋友圈”及“发送给朋友”接口,自定义的分享链接,其域名或路径必须与当前页面对应的公众号JS安全域名一致,否则将调用失 ...
- Java8系列 (三) Spliterator可分迭代器
本文转载自 jdk8 Stream 解析2 - Spliterator分割迭代器. 概述 我们最为常见的流的产生方式是 collection.stream(), 你点开Stream()方法, 他是通过 ...
- ADO.NET 二(Connection)
C# 语言中 Connection 类是 ADO.NET 组件连接数据库时第一个要使用的类,也是通过编程访问数据库的第一步. 接下来了解一下 Connection 类中的常用属性和方法,以及如何连接 ...
- 5_PHP数组_3_数组处理函数及其应用_7_数组排列函数
以下为学习孔祥盛主编的<PHP编程基础与实例教程>(第二版)所做的笔记. 数组排列函数 1. sort() 函数 程序: <?php $array = array("img ...
- 【转载】 C#中List集合使用First()方法获取第一个元素
在C#的List集合操作过程中,如果要获取List集合中的第一个元素对象,则一般会先通过获取到list[0]这种方式来获取第一个元素.其实在List集合中提供了获取最后一个元素的First()方法,调 ...
- 3.怪异盒模型box-sizing?弹性盒模型|盒布局?【HTML】
在标准模式下的盒模型:盒子总宽度/高度=width/height+padding+border+margin 在怪异模式下的盒模型下,盒子的总宽度和高度是包含内边距padding和边框border宽度 ...
- ActiveMQ Queue vs Topic vs VirtualTopic
之前写过一篇文章讨论VirtualTopic,但觉得不够透彻,这里再根据实验结果进行一次横向对比破除模糊和选择困难症. 文章中核心对比要素是:消息副本和负载均衡 Queue的特点和优势 ActiveM ...
- Android数据存储原理分析
Android上常见的数据存储方式为: SharedPreferences是 Android 中比较常用的存储方法,本篇将从源码角度带大家分析一下Android中常用的轻量级数据存储工具SharedP ...
- Hibernate hql getHibernateTemplate()常用方法汇总
转自:https://www.iteye.com/blog/zwdsmileface-2191943 getHibernateTemplate()常用方法 一.find(String queryStr ...