离线()

莫队

#include<bits/stdc++.h>
using namespace std;
const int N=50010,M=200100,K=1e6+2022;
int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9' || c<'0'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar(); 
    }
    return x*f;
}
int L,R,n,m,a[N],now[K],cnt,ans[M],tmp;
struct node{
    int l,r,x;
}e[M];
bool cmp(node t1,node t2){
    if(t1.l/tmp==t2.l/tmp)return t1.r<t2.r;
    return t1.l/tmp<t2.l/tmp;
}
void add(int t){
    if(t==0)return;
    t=a[t];
    now[t]++;
    if(now[t]==1)cnt++;
    return;
}
void del(int t){
    if(t==0)return;
    t=a[t];
    now[t]--;
    if(now[t]==0)cnt--;
    return;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    m=read();
    for(int i=1;i<=m;i++){
        e[i].l=read(),e[i].r=read();
        e[i].x=i;
    }
    tmp=sqrt(n);
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;i++){
        while(R<e[i].r)add(++R);
        while(L>e[i].l)add(--L);
        while(R>e[i].r)del(R--);
        while(L<e[i].l)del(L++);
        ans[e[i].x]=cnt;
    }
    for(int i=1;i<=m;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}

带修莫队

#include<bits/stdc++.h>
using namespace std;
const int N=133333+2022,M=1e6+2022;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
int ans[N],n,m,a[N],tmp,tot,cnt,now[M],L,R,sum,T;
struct node{
	int l,r,t,num;
}e[N];
struct SYS{
	int va,wz;
}x[N];
bool cmp(node t1,node t2){
	if(t1.l/tmp==t2.l/tmp && t1.r/tmp==t2.r/tmp)return t1.t<t2.t;
	if(t1.l/tmp==t2.l/tmp)return t1.r/tmp<t2.r/tmp;
	return t1.l/tmp<t2.l/tmp;
}
void add(int u){
	if(u==0)return;
	u=a[u];
	now[u]++;
	if(now[u]==1)sum++;
	return;
}
void del(int u){
	if(u==0)return;
	u=a[u];
	now[u]--;
	if(now[u]==0)sum--;
	return;
}
void time(int u){
	if(L<=x[u].wz && x[u].wz<=R){
		now[a[x[u].wz]]--;
		if(now[a[x[u].wz]]==0)sum--;
		now[x[u].va]++;
		if(now[x[u].va]==1)sum++;
	}
	swap(a[x[u].wz],x[u].va);
	return;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)a[i]=read();
	tmp=pow(n,0.666);
	for(int i=1;i<=m;i++){
		char opt;
		cin>>opt;
		int t1=read(),t2=read();
		if(opt=='Q'){
			e[++tot].l=t1,e[tot].r=t2;
			e[tot].num=tot;
			e[tot].t=cnt;
		}
		else{
			x[++cnt].wz=t1,x[cnt].va=t2;
		}
	}
	sort(e+1,e+tot+1,cmp);
	for(int i=1;i<=tot;i++){
		while(L<e[i].l)del(L++);
		while(R>e[i].r)del(R--);
		while(L>e[i].l)add(--L);
		while(R<e[i].r)add(++R);
		while(T<e[i].t)time(++T);
		while(T>e[i].t)time(T--); 
		ans[e[i].num]=sum;
	}
	for(int i=1;i<=tot;i++)
		printf("%d\n",ans[i]);
	return 0;
}

CDQ分治

————————

莫队

#include<bits/stdc++.h>
using namespace std;
const int N=50010,M=200100,K=1e6+2022;
int read(){
    int x=0,f=1;char c=getchar();
    while(c>'9' || c<'0'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0' && c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar(); 
    }
    return x*f;
}
int L,R,n,m,a[N],now[K],cnt,ans[M],tmp;
struct node{
    int l,r,x;
}e[M];
bool cmp(node t1,node t2){
    if(t1.l/tmp==t2.l/tmp)return t1.r<t2.r;
    return t1.l/tmp<t2.l/tmp;
}
void add(int t){
    if(t==0)return;
    t=a[t];
    now[t]++;
    if(now[t]==1)cnt++;
    return;
}
void del(int t){
    if(t==0)return;
    t=a[t];
    now[t]--;
    if(now[t]==0)cnt--;
    return;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    m=read();
    for(int i=1;i<=m;i++){
        e[i].l=read(),e[i].r=read();
        e[i].x=i;
    }
    tmp=sqrt(n);
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;i++){
        while(R<e[i].r)add(++R);
        while(L>e[i].l)add(--L);
        while(R>e[i].r)del(R--);
        while(L<e[i].l)del(L++);
        ans[e[i].x]=cnt;
    }
    for(int i=1;i<=m;i++){
        printf("%d\n",ans[i]);
    }
    return 0;
}

带修莫队

#include<bits/stdc++.h>
using namespace std;
const int N=133333+2022,M=1e6+2022;
int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9' || c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return x*f;
}
int ans[N],n,m,a[N],tmp,tot,cnt,now[M],L,R,sum,T;
struct node{
	int l,r,t,num;
}e[N];
struct SYS{
	int va,wz;
}x[N];
bool cmp(node t1,node t2){
	if(t1.l/tmp==t2.l/tmp && t1.r/tmp==t2.r/tmp)return t1.t<t2.t;
	if(t1.l/tmp==t2.l/tmp)return t1.r/tmp<t2.r/tmp;
	return t1.l/tmp<t2.l/tmp;
}
void add(int u){
	if(u==0)return;
	u=a[u];
	now[u]++;
	if(now[u]==1)sum++;
	return;
}
void del(int u){
	if(u==0)return;
	u=a[u];
	now[u]--;
	if(now[u]==0)sum--;
	return;
}
void time(int u){
	if(L<=x[u].wz && x[u].wz<=R){
		now[a[x[u].wz]]--;
		if(now[a[x[u].wz]]==0)sum--;
		now[x[u].va]++;
		if(now[x[u].va]==1)sum++;
	}
	swap(a[x[u].wz],x[u].va);
	return;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)a[i]=read();
	tmp=pow(n,0.666);
	for(int i=1;i<=m;i++){
		char opt;
		cin>>opt;
		int t1=read(),t2=read();
		if(opt=='Q'){
			e[++tot].l=t1,e[tot].r=t2;
			e[tot].num=tot;
			e[tot].t=cnt;
		}
		else{
			x[++cnt].wz=t1,x[cnt].va=t2;
		}
	}
	sort(e+1,e+tot+1,cmp);
	for(int i=1;i<=tot;i++){
		while(L<e[i].l)del(L++);
		while(R>e[i].r)del(R--);
		while(L>e[i].l)add(--L);
		while(R<e[i].r)add(++R);
		while(T<e[i].t)time(++T);
		while(T>e[i].t)time(T--); 
		ans[e[i].num]=sum;
	}
	for(int i=1;i<=tot;i++)
		printf("%d\n",ans[i]);
	return 0;
}

CDQ分治