[国家集训队]数颜色 / 维护队列

考虑这是一个带修改的莫队。
我们多加一维时间轴。
发现这个修改是很平凡的。
所以我们的操作也就从二维转到了三维。
记录每个查询要修改的操作次数,多了就还原,少了就去掉。

[国家集训队]数颜色 / 维护队列
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 1400000

int n,m,a[N];

char k;

ll cntq,cntr;

struct P{
	int l,r,t,id;
}qq[N],qr[N];

ll sz;

bool cmp(P a,P b){
	return (a.l / sz == b.l / sz) ? (a.r / sz == b.r / sz) ? a.t < b.t : a.r < b.r : a.l < b.l;
}

ll c[N],ans[N],qans;

inline void add(ll x){qans += !c[x] ++ ;}
inline void del(ll x){qans -= ! -- c[x];}
inline void modity(ll i,ll ct){
	if(qr[ct].l >= qq[i].l && qr[ct].l <= qq[i].r){
	del(a[qr[ct].l]);
	add(qr[ct].r);
	}
	std::swap(a[qr[ct].l],qr[ct].r);
}

int main(){
	scanf("%d%d",&n,&m);
	sz = pow(n,0.66666);
	for(int i = 1;i <= n;++i)
	scanf("%d",&a[i]);
	for(int i = 1;i <= m;++i){
		while(k != 'R' && k != 'Q')
		k = getchar();
		ll l,r;
		scanf("%d%d",&l,&r);
		if(k == 'Q'){
			qq[++cntq].l = l;
			qq[cntq].r = r; 
			qq[cntq].id = cntq;
			qq[cntq].t = cntr;
		}
		else
		qr[++cntr].l = l,qr[cntr].r = r;
		k = 'Z';
	}
	std::sort(qq + 1,qq + cntq + 1,cmp);
	ll l = 0,r = 0,t = 0;
	for(int i = 1;i <= cntq;++i){
		while(l < qq[i].l)del(a[l ++ ]);
		while(l > qq[i].l)add(a[-- l]);
		while(r > qq[i].r)del(a[r --]);
		while(r < qq[i].r)add(a[++ r]);
		while(t < qq[i].t)modity(i,++t);
		while(t > qq[i].t)modity(i,t--);
		ans[qq[i].id] = qans;
	}
	for(int i = 1;i <= cntq;++i)
	std::cout<<ans[i]<<std::endl;
}
posted @ 2021-04-22 20:33  fhq_treap  阅读(55)  评论(0编辑  收藏  举报