题目描述:

墨墨购买了一套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≤50000,M≤50000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

本题可能轻微卡常数

思路:

本题为带修莫队模板题,在普通莫队的基础上引入时间维度,可以支持时间推移和时间倒流。跑主算法时定义当前时间戳为t,对于每个查询操作,如果当前时间戳大于查询的时间戳,说明已进行的修改操作比要求的多,就把之前改的改回来,如果当前时间戳小于查询的时间戳,说明还应再往后修改。只有当当前区间和查询区间左右端点、时间戳均重合时,才认定区间完全重合,此时的答案才是本次查询的最终答案。

在排序中加入第三关键字t(时间),按着l到r再到t的顺序排,分块大小应为n^(2/3),在最后for循环的while中加入两个关于时间的while来调整当前时间与查询时间的关系。

因为移完t t做完一处修改后,有可能要改回来,所以我们还要把原值存好备用。但其实我们也可以不存,只要在修改后把修改操作的值和原值swap一下,那么改回来时也只要swap一下,swap两次相当于没搞,就改回来了。

代码::

 #include <iostream>
#include <cmath>
#include <algorithm>
#define max_n 50005
using namespace std;
int n,m;
int a[max_n];
int belong[max_n*];
int ans[max_n];
int cnt[]; struct query
{
int l;
int r;
int id;
int t;
}q[max_n];
struct modify
{
int pos;
int col;
int last;
}c[max_n];
int size;
int bulk;
int cntq = ;
int cntc = ;
int cmp(query a,query b)
{
return (belong[a.l]^belong[b.l])? belong[a.l]<belong[b.l]:((belong[a.r]^belong[b.r])?belong[a.r]<belong[b.r]:a.t<b.t);
}
int main()
{
cin >> n >> m;
size = pow(n,2.0/3.0);
bulk = ceil((double)n/size);
for(int i = ;i<=bulk;i++)
{
for(int j = (i-)*size+;j<=i*size;j++)
{
belong[j] = i;
}
}
for(int i = ;i<=n;i++)
{
cin >> a[i];
}
char opt;
for(int i = ;i<=m;i++)
{
cin >> opt;
switch(opt)
{
case 'Q':
cin >> q[++cntq].l;
cin >> q[cntq].r;
q[cntq].t = cntc;
q[cntq].id= cntq;
break;
case 'R':
cin >> c[++cntc].pos;
cin >> c[cntc].col;
}
}
sort(q+,q+cntq+,cmp);
int l = ;
int r = ;
int time = ;
int now = ;
for(int i = ;i<=cntq;i++)
{
int ql = q[i].l;
int qr = q[i].r;
int qt = q[i].t;
while(l<ql) now -= !--cnt[a[l++]];
while(l>ql) now += !cnt[a[--l]]++;
while(r>qr) now -= !--cnt[a[r--]];
while(r<qr) now += !cnt[a[++r]]++;
while(time<qt)
{
++time;//时间向后推移
if(ql<=c[time].pos&&c[time].pos<=qr)//如果当前(time时)位置与查询区间重合,说明time时已经统计过c[time].pos处的元素,并且是以旧的时间的未修改的这个元素完成统计的
{//压缩的运算表达式
now -= !--cnt[a[c[time].pos]]-!cnt[c[time].col]++;
//now是存的答案,c[time].pos是在time时修改的位置,a[c[time].pos]是在该位置原来的元素,注意now后是-=
//这句含义是1.如果在time时刻修改的位置(因为现在是时间还在往前走)上的元素的个数减少到零,now就减少一(因为这个元素已成为历史)
//c[time].col是在time时刻修改后的颜色
//2.如果对于在time时刻修改过的元素,它的个数为0,就将元素个数自增,然后now在加一(因为随着时间推移,发现了新的元素种类)
}
swap(a[c[time].pos],c[time].col);
//让这个新元素(c[time].col)成为历史,用a[c[time].pos]暂时存储,
//而c[time].col里是暂存原来被修改掉的元素
}
while(qt<time)
{
if(ql<=c[time].pos&&c[time].pos<=qr)
{
now -= !--cnt[a[c[time].pos]]-!cnt[c[time].col]++;
//同上
}
swap(a[c[time].pos],c[time].col);
//同上
--time;
}
ans[q[i].id] = now;
}
for(int i = ;i<=cntq;i++)
{
cout << ans[i] << endl;
}
return ;
}

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

  1. 洛谷 P1903 [国家集训队]数颜色 / 维护队列 带修莫队

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

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

    #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...

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

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

  4. luogu 1903 [国家集训队]数颜色 / 维护队列 带修改莫队

    十分玄学的数据结构~ code: #include <bits/stdc++.h> #define N 1000006 #define setIO(s) freopen(s".i ...

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

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

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

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

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

    题意:有两种操作: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col. 对每个1操作 输出答案: 带修莫队 模板题 (加 ...

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

    思路 带修莫队的板子 带修莫队只需要多维护一个时间的指针即可,记录一下每个询问在第几次修改之后,再回退或者前进几个修改操作 排序的时候如果a.l和b.l在一个块里,就看r,如果a.r和b.r在一个块里 ...

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

    传送门 解题思路 带修莫队,第一次写,其实和普通莫队差不多,就是多了个时间轴,块分n^(2/3)最优,时间复杂度O(n^(5/3)). #include<iostream> #includ ...

随机推荐

  1. 一键安装docker-ce

    curl https://get.docker.com |env CHANNEL=stable sudo sh -s docker --mirror Aliyun

  2. acme自动证书申请

    安装acme.sh curl https://get.acme.sh | sh acme.sh默认安装到了当前家目录. [root@iZbp17hycbhnayg00ohec9Z ~]# ~/.acm ...

  3. android基础---->Toast的使用

    简要说明 Toast是一种没有交点,显示时间有限,不能与用户进行交互,用于显示提示信息的显示机制,我们可以把它叫做提示框.Toast不依赖 于Activity,也就是说,没有Activity,依然可以 ...

  4. leetcode腾讯精选练习(50 题)(持续更新)

    1.除自身以外数组的乘积 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘 ...

  5. TCP/IP学习笔记16--TCP--特点,数据重发,连接管理,段

    TCP充分实现了数据传输时各种控制功能,可以进行丢包时的重发控制,还可以对次序乱掉的包进行顺序控制,这些在UDP中都是没有的.UDP是一种没有复杂控制,提供面向无连接通信服务的一种协议.TCP是面向有 ...

  6. 深度解析qml引擎---(2)绑定(binding)

    强烈的希望是人生中比任何欢乐更大的兴奋剂.--尼采 上一篇文章讲了QML引擎加载qml文件的过程,大体过程是,解析qml文件,然后为文件中的每个元素创建对应的c++对象.例如,qml文件中如果使用了T ...

  7. 使用TCP的协议有哪些?使用UDP的协议有哪些?

    运行于TCP协议之上的协议: HTTP协议:超文本传输协议,用于普通浏览 HTTPS协议:安全超文本传输协议,身披SSL外衣的HTTP协议 FTP协议:文件传输协议,用于文件传输 POP3协议:邮局协 ...

  8. maven dependency中provided和compile的区别

    重点:这个项目打成war包时,scope=provided的jar包,不会出现在WEB-INFO/lib目录下,而scope=compile的jar包,会放到WEB-INFO/lib目录 scope= ...

  9. 转载:MFC之MessageBox、AfxMessageBox用法

    在软件中我们经常会弹出个小窗口,给一点点提示.这就会用到消息对话框. 在Win32 API程序中只有MessageBox这一种用法. 而在MFC中就有三各方法: .调用API中的MessageBox: ...

  10. 【flask】登陆后返回之前重定向跳转的页面

    登陆后返回之前重定向跳转的页面 一.前言 实现强制跳转到登陆页面,登陆后返回之前的页面的功能.网上跳登陆页面的很多:返回之前页面功能没多少.这里我只是用了自己的方法,有缺点和其他方法也请指点!(´ε` ...