P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队
\(\color{#0066ff}{ 题目描述 }\)
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
为了满足墨墨的要求,你知道你需要干什么了吗?
\(\color{#0066ff}{输入格式}\)
第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。
第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。
第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。
\(\color{#0066ff}{输出格式}\)
对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。
\(\color{#0066ff}{输入样例}\)
6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6
\(\color{#0066ff}{输出样例}\)
4
4
3
4
\(\color{#0066ff}{数据范围与提示}\)
对于100%的数据,N≤50000,M≤50000,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
\(\color{#0066ff}{ 题解 }\)
可以用莫队做,但是带修改
带修改的莫队,我们以\(n^{\frac 2 3}\)为一块,这样总复杂度为\(O(n^{\frac 5 3})\),懒得证明了qwq
排序时以左端点的块为第一关键字,右端点的块为第二关键字,时间为第三关键字
每次到一个问题,如果当前修改的少了,就一直修改到当前位置,如果多了则撤销
开个数组记录当前修改的位置的上一次的颜色,便于撤销,就解决了
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int len = 1357;
const int maxn = 5e4 + 10;
int bel[maxn];
struct node {
int l, r, id;
friend bool operator < (const node &a, const node &b) {
if(bel[a.l] != bel[b.l]) return bel[a.l] < bel[b.l];
if(bel[a.r] != bel[b.r]) return bel[a.r] < bel[b.r];
return a.id < b.id;
}
}e[maxn], c[maxn];
int ans[maxn], a[maxn], t[1005050], pre[maxn];
int l = 1, r = 0, tot, now;
int n, m, qnum, cnum;
char getch() {
char ch;
while(!isalpha(ch = getchar()));
return ch;
}
void add(int i) {
if(!t[i]) tot++;
t[i]++;
}
void del(int i) {
t[i]--;
if(!t[i]) tot--;
}
void change_add(int id) {
if(l <= c[id].l && c[id].l <= r) del(a[c[id].l]), add(c[id].r);
pre[id] = a[c[id].l];
a[c[id].l] = c[id].r;
}
void change_del(int id) {
if(l <= c[id].l && c[id].l <= r) del(c[id].r), add(pre[id]);
a[c[id].l] = pre[id];
}
void work(int tme) {
while(now < cnum && c[now + 1].id <= tme) change_add(++now);
while(now && c[now].id > tme) change_del(now--);
}
int main() {
n = in(), m = in();
for(int i = 1; i <= n; i++) a[i] = in(), bel[i] = (i - 1) / len + 1;
for(int i = 1; i <= m; i++) {
if(getch() == 'Q') {
qnum++;
e[qnum].l = in(), e[qnum].r = in(), e[qnum].id = i;
}
else {
cnum++;
c[cnum].l = in(), c[cnum].r = in(), c[cnum].id = i;
}
}
std::sort(e + 1, e + qnum + 1);
for(int i = 1; i <= qnum; i++) {
work(e[i].id);
while(l < e[i].l) del(a[l++]);
while(l > e[i].l) add(a[--l]);
while(r > e[i].r) del(a[r--]);
while(r < e[i].r) add(a[++r]);
ans[e[i].id] = tot;
}
for(int i = 1; i <= m; i++) if(ans[i]) printf("%d\n", ans[i]);
return 0;
}
P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队的更多相关文章
- P1903 [国家集训队]数颜色 / 维护队列 带修改莫队
题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...
- 洛谷 P1903 [国家集训队]数颜色 / 维护队列 带修莫队
题目描述 墨墨购买了一套\(N\)支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: \(1\). \(Q\) \(L\) \(R\)代表询问你从第\(L\) ...
- bzoj2120 / P1903 [国家集训队]数颜色 / 维护队列(带修改莫队)
P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队 在原有指针$(l,r)$上又添加了时间指针$t$ 贴一段dalao的解释 带修改的莫队,和原版莫队相比,多了一个时间轴 原版莫队是将区间( ...
- Luogu P1903 [国家集训队]数颜色 / 维护队列 (带修莫队)
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> ...
- luogu 1903 [国家集训队]数颜色 / 维护队列 带修改莫队
十分玄学的数据结构~ code: #include <bits/stdc++.h> #define N 1000006 #define setIO(s) freopen(s".i ...
- P1903 [国家集训队]数颜色 / 维护队列(带修莫队)
题目描述: 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. ...
- 洛谷P1903 [国家集训队]数颜色 / 维护队列 ( 带 修 )
题意:有两种操作: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col. 对每个1操作 输出答案: 带修莫队 模板题 (加 ...
- P1903 [国家集训队]数颜色 / 维护队列(莫队区间询问+单点修改)
题目链接:https://www.luogu.org/problemnew/show/P1903 题目大意:中文题目 具体思路:莫队单点修改+区间询问模板题,在原来的区间询问的基础上,我们要记录当前这 ...
- P1903 [国家集训队]数颜色 / 维护队列
思路 带修莫队的板子 带修莫队只需要多维护一个时间的指针即可,记录一下每个询问在第几次修改之后,再回退或者前进几个修改操作 排序的时候如果a.l和b.l在一个块里,就看r,如果a.r和b.r在一个块里 ...
随机推荐
- SQL 用;with 由所有的子节点查询到树结构中所有父节点
1.所有的子节点查询到树结构中所有父节点 RETURNS @Tree Table(PID )) as begin --DECLARE @ID VARCHAR() --SET @ID = ' ;with ...
- Pythonb编码规范
本编码规范是对知道创宇研发技能表中提供的PythonCodingRule.pdf文档进行凝练和总结出来的结果,感谢知道创宇的Geek精神与分享精神 此规范较为严格,严格规定了编码格式和命名规则,仅适于 ...
- PHP函数(五)-回调函数
回调函数是指调用函数的时候将另一个函数作为参数传递到调用的函数中,而不是传递一个普通的变量作为参数 使用回调函数是为了可以将一段自己定义的功能传到函数内部使用 声明回调函数的方法 变量函数声明 < ...
- 2015.3.12Arinc424 Tools中SiniArincCls.csParserFile(string sFile)函数正则表达式理解
原文: string RegEx1 = @"(\[ITEM\]\s*=[\S\s]*?(?=\[ITEM\])|\[ITEM\]\s*=[\S\s]*)";//用来识别主记录和后续 ...
- rsync 简单使用 非默认ssh端口 分别从远程获取及推送本地的文件到远程
rsync: did not see server greetingrsync error: error starting client-server protocol (code 5) at mai ...
- java 多线程系列基础篇(一)
多线程状态图: Thread类的两个方法比较: yield方法: Yield是一个静态的原生(native)方法 Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程. Yiel ...
- git clone 某一特定分支<转>
网上搜索自己想要的答案,往往会搜大一大堆感觉没用的,或者看不懂的东西, 最好终于找到了想要答案,特记录一下: ============================================= ...
- C# WinForm 关闭登陆窗体后进程还再内存怎么办?
问题:我们通常再制作WinForm应用程序的时候,运行程序的第一个窗口一般是登陆窗口.代码如下: 那么这种方式有一个弊端,这种启动方式,其实就是把登陆窗口设置为主窗体.因此,再登陆后,我们通常是调用H ...
- 4-EasyNetQ之Logging(黄亮翻译)
EasyNetQ提供了一个Logger接口 IEasyNetQLogger: public interface IEasyNetQLogger { void DebugWrite(string for ...
- struts2学习笔记(2)action多个方法的动态调用
①在struts.xml中的action添加method <action name="addhelloworld" method="add" class= ...