题目描述
墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。
墨墨会像你发布如下指令:
- 1 1 1、 Q Q Q L L L R R R代表询问你从第 L L L支画笔到第 R R R支画笔中共有几种不同颜色的画笔。
- 2 2 2、 R R R P P P C o l Col Col 把第 P P P支画笔替换为颜色 C o l Col Col。为了满足墨墨的要求,你知道你需要干什么了吗?
题解
如果没有修改操作,就是莫队的板子题。
带上操作以后,我们只要在原始的莫队上面加上一维时间;在每一次转移的时候,区间转移完以后再转移第三维时间。至于具体的转移方法,我们就再维护一个时间的指针即可;对新修改的数和原序列的数进行交换:注意不能直接复制,因为会出现从时间减少的情况。
细节:
- 块为 n 1 3 n^{\frac{1}{3}} n31,总时间复杂度是: O ( n 3 5 ) . O(n^{\frac{3}{5}}). O(n53).
- 初始化
l
=
1
,
r
=
0
,
t
=
0.
l=1,r=0,t=0.
l=1,r=0,t=0.
具体为什么我也不知道。
代码如下:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
int n,m,T;
int t1 = 0;
int t2 = 0;
int ans = 0;
int a[2000000];
int Ans[2000000];
int cnt[2000000];
struct ques
{
int L,R,id,t;
int p;
friend bool operator < (ques p1, ques p2)
{
if (p1.p ^ p2.p) return p1.p < p2.p;
if (p1.R ^ p2.R) return p1.R < p2.R;
return p1.t < p2.t;
}
} q[2000000];
struct node {
int pos,val;
} c[2000000];
inline int read(void)
{
int s = 0, w = 1;char c = getchar();
while (c<'0' || c>'9') {if (c == '-') w = -1; c = getchar();}
while (c>='0' && c<='9') s = s*10+c-48,c = getchar();
return s*w;
}
void ins(int x)
{
cnt[a[x]] ++;
if (cnt[a[x]] == 1) ans ++;
return;
}
void del(int x)
{
cnt[a[x]] --;
if (cnt[a[x]] == 0) ans --;
return;
}
void Change(int t,int l,int r)
{
if (c[t].pos >= l && c[t].pos <= r)
{
cnt[a[c[t].pos]] --;
if (cnt[a[c[t].pos]] == 0) ans --;
cnt[c[t].val] ++;
if (cnt[c[t].val] == 1) ans ++;
}
swap(a[c[t].pos],c[t].val);
return;
}
int main(void)
{
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
n = read();
m = read();
T = pow(n, 2.0 / 3.0);
for (int i=1;i<=n;++i) a[i] = read();
for (int i=1;i<=m;++i)
{
char ch = getchar();
while (ch ^ 'Q' && ch ^ 'R') ch = getchar();
if (ch == 'Q') q[++t1] = ques{read(), read(), t1, t2};
if (ch == 'R') c[++t2] = node{read(), read()};
if (ch == 'Q') q[t1].p = (q[t1].L + T -1) / T;
}
sort(q+1, q+t1+1);
int l = 1;
int r = 0;
int t = 0;
ans = 0;
for (int i=1;i<=t1;++i)
{
while (l > q[i].L) ins(--l);
while (r < q[i].R) ins(++r);
while (l < q[i].L) del(l++);
while (r > q[i].R) del(r--);
while (t < q[i].t) Change(++t,q[i].L,q[i].R);
while (t > q[i].t) Change(t--,q[i].L,q[i].R);
Ans[q[i].id] = ans;
}
for (int i=1;i<=t1;++i) printf("%d\n", Ans[i]);
return 0;
}