题意
待修莫队模板题
思路
待修莫队在普通莫队的基础上,额外维护一个修改操作,每一次根据查询操作的时间加入修改或是撤销修改。
实现蛮显然的,配合代码很容易搞懂。
note:块大小的证明参见这里,此处不做赘述。
代码
#include <bits/stdc++.h>
using namespace std;
namespace StandardIO {
template<typename T>inline void read (T &x) {
x=0;T f=1;char c=getchar();
for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
x*=f;
}
template<typename T>inline void write (T x) {
if (x<0) putchar('-'),x*=-1;
if (x>=10) write(x/10);
putchar(x%10+'0');
}
}
using namespace StandardIO;
namespace Project {
const int N=200200;
int n,m,block;
int a[N];
int qcnt,ucnt;
struct ask {
int l,r,t,id;
} q[N];
struct upd {
int x,pre,now;
} u[N];
int cnt[1000001],ans[N],res;
inline bool cmp (const ask x,const ask y) {
return (x.l/block!=y.l/block)?(x.l/block<y.l/block):((x.r/block!=y.r/block)?(x.r/block<y.r/block):x.t<y.t);
}
inline void MAIN () {
read(n),read(m);
for (register int i=1; i<=n; ++i)
read(a[i]);
for (register int i=1; i<=m; ++i) {
scanf("
");
if (getchar()=='Q') {
++qcnt,read(q[qcnt].l),read(q[qcnt].r),q[qcnt].t=ucnt,q[qcnt].id=qcnt;
} else {
++ucnt,read(u[ucnt].x),read(u[ucnt].now),u[ucnt].pre=a[u[ucnt].x],a[u[ucnt].x]=u[ucnt].now;
}
}
for (register int i=ucnt; i; --i)
a[u[i].x]=u[i].pre;
block=ceil(exp((log(n)+log(ucnt))/3)),sort(q+1,q+qcnt+1,cmp);
int l=1,r=0,t=0;
for (register int i=1; i<=qcnt; ++i) {
while (l>q[i].l) res+=!cnt[a[--l]]++;
while (l<q[i].l) res-=!--cnt[a[l++]];
while (r<q[i].r) res+=!cnt[a[++r]]++;
while (r>q[i].r) res-=!--cnt[a[r--]];
while (q[i].t<t) {
int x=u[t].x;
if (l<=x&&x<=r) res-=!--cnt[a[x]];
a[x]=u[t--].pre;
if (l<=x&&x<=r) res+=!cnt[a[x]]++;
}
while (q[i].t>t) {
int x=u[++t].x;
if (l<=x&&x<=r) res-=!--cnt[a[x]];
a[x]=u[t].now;
if (l<=x&&x<=r) res+=!cnt[a[x]]++;
}
ans[q[i].id]=res;
}
for (register int i=1; i<=qcnt; ++i) {
write(ans[i]),puts("");
}
}
}
int main () {
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
Project::MAIN();
}