洛谷P1903 [国家集训队]数颜色 / 维护队列
1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。
2、 R P Col 把第P支画笔替换为颜色Col。
带修改莫队;
学玩普通莫队再看带修改莫队,OI-wiki上讲的通俗易懂;
对比主要是这几点:
1.分块unit = pow(n,2.0/3.0);
2.对询问排序是先排左区间是否在同一个块,再排右区间,然后是时间
3.将询问和修改划分成两个数组,莫队将左右指针移动到询问区间过后再考虑修改问题,已知本次询问的time,然后在修改数组上将time之前的修改都跑一遍,其中修改值与被修改值是swap相互替换,因为可能要回退,也就是换回来。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define Pair pair<LL,LL>
#define ls rt<<1
#define rs rt<<1|1
#define Pi acos(-1.0)
#define eps 1e-6
#define DBINF 1e100
#define mod 1000000007
#define MAXN 1e18
#define MS 1000009
LL n,m;
int a[MS];
struct node{
int l,r,id;
}ask[MS];
int asknum;
int unit;
struct nod{
int pos,tar,id;
}alt[MS];
int altnum;
int v[MS];
int ac[MS];
bool cmp(node t1,node t2){
if(t1.l/unit != t2.l/unit) return t1.l < t2.l;
if(t1.r/unit != t2.r/unit) return t1.r < t2.r;
return t1.id < t2.id;
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i=1;i<=n;i++){
cin >> a[i];
}
for(int i=1;i<=m;i++){
char op;
cin >> op;
if(op == 'Q'){
int l,r;
cin >> l >> r;
ask[++asknum] = {l,r,i};
}
else if(op == 'R'){
int pos,tar;
cin >> pos >> tar;
alt[++altnum] = {pos,tar,i};
}
}
unit = pow(n,2.0/3.0);
sort(ask+1,ask+asknum+1,cmp);
int ans = 0;
int L = 1 ,R = 0;
int time = 0;
for(int i=1;i<=asknum;i++){
int l = ask[i].l;
int r = ask[i].r;
int id = ask[i].id;
while(L < l){
v[a[L]]--;
if(v[a[L]] == 0) ans--;
L++;
}
while(L > l){
L--;
v[a[L]]++;
if(v[a[L]] == 1) ans++;
}
while(R < r){
R++;
v[a[R]]++;
if(v[a[R]] == 1) ans++;
}
while(R > r){
v[a[R]]--;
if(v[a[R]] == 0) ans--;
R--;
}
while(alt[time+1].id < id && time+1 <= altnum){
time++;
int altpos = alt[time].pos;
int alttar = alt[time].tar;
if(L <= altpos && altpos <= R){
v[a[altpos]]--;
if(v[a[altpos]] == 0) ans--;
swap(a[altpos],alt[time].tar);
v[a[altpos]]++;
if(v[a[altpos]] == 1) ans++;
}
else{
swap(a[altpos],alt[time].tar);
}
}
while(alt[time].id > id){
int altpos = alt[time].pos;
int alttar = alt[time].tar;
if(L <= altpos && altpos <= R){
v[a[altpos]]--;
if(v[a[altpos]] == 0) ans--;
swap(a[altpos],alt[time].tar);
v[a[altpos]]++;
if(v[a[altpos]] == 1) ans++;
}
else{
swap(a[altpos],alt[time].tar);
}
time--;
}
ac[ask[i].id] = ans;
}
for(int i=1;i<=m;i++){
if(ac[i]){
cout << ac[i] << "\n";
}
}
return 0;
}