【Dynamic len(set(a[L:R]))】 题解
【\(solution\)】
这是一道带修莫队模板题。
这道题目和P1903基本上相同,只是查询的区间是 \([L,R - 1]\) , 数组的下标是 \([0,N - 1]\) 。
带修莫队的写法和普通莫队基本相同,只是再加一维时间轴 \(Time\) 表示现在的询问操作是否要被修改.
排序的时候相较于普通莫队还要加上一个关键字: 经历的修改次数 ,先询问的排前面。
inline bool CMP(Query a,Query b)
{
return (a.x / block) == (b.x / block) ? (a.y / block == b.y / block ? a.pre < b.pre : a.y < b.y) : a.x < b.x;
}
之后就是套上普通莫队即可。
- 建议块的大小调整为 $ n ^ \frac{2}{3}$ ,证明我不会,反正跑的更快。
- 写莫队的时候设初始的 \(l\),\(r\) 分别为 \(1\),\(0\) ,设 \(l\) 为 \(0\) 时容易 \(RE\) (
别问我怎么知道的)
【\(Code\)】
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int Maxk = 2e6;
int n,m,sum,cnt_Q,cnt_s,block,now;
int a[Maxk],ans[Maxk],cnt[Maxk];
struct node{
int past;
int color;
}s[Maxk];//修改
struct Query{
int x;
int y;
int pre;
int id;
}Q[Maxk];
inline int read()
{
int x = 0,f = 0;char ch = getchar();
while(!isdigit(ch)) f |= ch == '-',ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48),ch = getchar();
return f ? -x : x;
}
inline bool CMP(Query a,Query b)
{
return (a.x / block) == (b.x / block) ? (a.y / block == b.y / block ? a.pre < b.pre : a.y < b.y) : a.x < b.x;
}
inline void add(int x)
{
if(++ cnt[a[x]] == 1) sum ++;
return;
}
inline void del(int x)
{
if(-- cnt[a[x]] == 0) sum --;
return;
}
void solve(int now,int i)
{
if(s[now].past >= Q[i].x && s[now].past <= Q[i].y) {
//只有修改在查询的区间内才会对查询的结果产生影响
if(-- cnt[a[s[now].past]] == 0) sum --;
if(++ cnt[s[now].color] == 1) sum ++;
}
swap(s[now].color ,a[s[now].past]);
return;
}
void work()
{
int l = 1,r = 0;now = 0;
for(int i = 1;i <= cnt_Q;i ++) {
int ql = Q[i].x;
int qr = Q[i].y;
while(l < ql) del(l ++);
while(l > ql) add(-- l);
while(r > qr) del(r --);
while(r < qr) add(++ r);//模板
while(now < Q[i].pre) solve(++ now,i); //改少了,改过去
while(now > Q[i].pre) solve(now --,i); //改多了,改回来
ans[Q[i].id] = sum;
}
for(int i = 1;i <= cnt_Q;i ++) {
printf("%d\n",ans[i]);
}
return;
}
signed main()
{
n = read(),m = read();
for(int i = 1;i <= n;i ++) a[i] = read();
block = pow(n,(double) 2.0 / 3.0);
while(m --) {
char c; cin >> c;
if( c == 'Q') {
Q[++ cnt_Q].x = read() + 1;
Q[cnt_Q].y = read();
Q[cnt_Q].pre = cnt_s;//记录最近的修改位置
Q[cnt_Q].id = cnt_Q;//记录编号
}
else {
s[++ cnt_s].past = read() + 1;
s[cnt_s].color = read();
}
}
sort(Q + 1,Q + cnt_Q + 1,CMP);
work();
return 0;
}

浙公网安备 33010602011771号