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

题目来源https://www.luogu.com.cn/problem/P1903

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

题目描述

墨墨购买了一套 N 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:

  1. Q L R 代表询问你从第 L 支画笔到第 R 支画笔中共有几种不同颜色的画笔。

  2. R P Col 把第 P 支画笔替换为颜色 Col

为了满足墨墨的要求,你知道你需要干什么了吗?

输入格式

1 行两个整数 NM,分别代表初始画笔的数量以及墨墨会做的事情的个数。

2N 个整数,分别代表初始画笔排中第 i 支画笔的颜色。

3 行到第 2+M 行,每行分别代表墨墨会做的一件事情,格式见题干部分。

输出格式

对于每一个 Query 的询问,你需要在对应的行中给出一个数字,代表第 L 支画笔到第 R 支画笔中共有几种不同颜色的画笔。

样例 #1

样例输入 #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

提示

对于30%的数据,n,m10000

对于60%的数据,n,m50000

对于所有数据,n,m133333

所有的输入数据中出现的所有整数均大于等于 1 且不超过 106

本题可能轻微卡常数

来源:bzoj2120

本题数据为洛谷自造数据,使用 CYaRon 耗时5分钟完成数据制作。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int n, m, block, l = 1, r = 0, ans;
int a[52113140], cnt[52113140], out[5211314], pos[5211314];
int ask_num, add_num;
string str;
struct ASK {
int lift, right, time, identity;
}ask[5211314];
struct ADD {
int pos, num;
}add[5211314];
inline int read() {
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-') f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch - '0');
ch = getchar();
}
return x * f;
}
inline bool cmp_pretreat(const ASK &a, const ASK &b) {
if (pos[a.lift] != pos[b.lift]) return pos[a.lift] < pos[b.lift];
if (pos[a.right] != pos[b.right]) return pos[a.right] < pos[b.right];
return a.time < b.time;
}
inline void Del(int position) {
if (-- cnt[a[position]] == 0) ans --;
return;
}
inline void Add(int position) {
if (cnt[a[position]] ++ == 0) ans ++;
return;
}
inline void Time(int update) {
if (add[update].pos < l || add[update].pos > r) {
swap(add[update].num, a[add[update].pos]);
}
else {
Del(add[update].pos);
swap(add[update].num, a[add[update].pos]);
//若第update次修改后,则下一次time再到update一定是撤销
Add(add[update].pos);
}
return;
}
int main() {
ask[0].time = 0;
cin >> n >> m;
block = pow(n, 1.00*2/3);
for (int i = 1; i <= n; ++ i) {
a[i] = read();
pos[i] = (i - 1) / block + 1;
}
for (int i = 1; i <= m; ++ i) {
cin >> str;
if (str == "Q") {
ask_num ++;
ask[ask_num].lift = read();
ask[ask_num].right = read();
ask[ask_num].time = add_num;
ask[ask_num].identity = ask_num;
}
else {
add_num ++;
add[add_num].pos = read();
add[add_num].num = read();
}
}
stable_sort(ask + 1, ask + 1 + ask_num, cmp_pretreat);
for (int i = 1, t = 0; i <= ask_num; ++ i) {
while (l < ask[i].lift) Del(l ++);
while (l > ask[i].lift) Add(-- l);
while (r < ask[i].right) Add(++ r);
while (r > ask[i].right) Del(r --);
while (ask[i].time > t) Time(++ t);
while (ask[i].time < t) Time(t --);//注意顺序
out[ask[i].identity] = ans;
}
for (int i = 1; i <= ask_num; ++ i) {
printf("%d\n",out[i]);
}
return 0;
}
posted @   觉清风  阅读(20)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示