题目来源https://www.luogu.com.cn/problem/P1903
[国家集训队] 数颜色 / 维护队列
题目描述
墨墨购买了一套 \(N\) 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会向你发布如下指令:
-
\(Q\ L\ R\) 代表询问你从第 \(L\) 支画笔到第 \(R\) 支画笔中共有几种不同颜色的画笔。
-
\(R\ P\ Col\) 把第 \(P\) 支画笔替换为颜色 \(Col\)。
为了满足墨墨的要求,你知道你需要干什么了吗?
输入格式
第 \(1\) 行两个整数 \(N\),\(M\),分别代表初始画笔的数量以及墨墨会做的事情的个数。
第 \(2\) 行 \(N\) 个整数,分别代表初始画笔排中第 \(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,m \leq 10000\)
对于60%的数据,\(n,m \leq 50000\)
对于所有数据,\(n,m \leq 133333\)
所有的输入数据中出现的所有整数均大于等于 \(1\) 且不超过 \(10^6\)。
本题可能轻微卡常数
来源: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]);
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;
}
标签:ch,画笔,int,Luogu,P1903,add,num,ask,国家集训队
From: https://www.cnblogs.com/jueqingfeng/p/17430777.html