数颜色 题解

时间:2020-05-17
本文章向大家介绍数颜色 题解,主要包括数颜色 题解使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

没想到吧,我大莫队也能修改!

对于每次询问,按左端点所在块为第一关键字,右端点所在块为第二关键字,影响它的上一个询问为第三关键字进行排序。

在每次处理询问时,同时对时间戳进行移动,将修改的贡献算出来。

#include <bits/stdc++.h>
using namespace std;
inline long long read() {
	long long ans = 0;
	char last = ' ', ch = getchar();
	while (ch < '0' || ch > '9') last = ch, ch = getchar();
	while (ch >= '0' && ch <= '9') ans = ans * 10 + ch -'0', ch = getchar();
	if (last == '-') return -ans;
	return ans;
}
void write(int x) {
	if (x > 9) write(x / 10);
	putchar(x%10 + '0');
}
const int N=133333+10;
int n,m;
int pos[N],co[N],len;
struct query {
	int l,r,pre,id;
} q[N];
struct change {
	int x,y;
} c[N];
int qn,cn;
char opt;
void build() {
	for(int i=1; i<=n; i++)
		pos[i]=(i-1)/len+1;
}
bool cmp(query _,query __) {
	return (_.l/len)==(__.l/len)?_.r<__.r:(_.l/len)<(__.l/len);
}
int ans,L=1,R,now,cnt[1000010],tans[N];
void add(int x) {
	if(++cnt[x]==1)
		ans++;
	//printf("use add %d\n",ans);
}
void del(int x) {
	if(--cnt[x]==0)
		ans--;
	//printf("use del %d\n",ans);
}
void work(int t,int i) {
	if(c[t].x<=q[i].r&&c[t].x>=q[i].l) {
		if(--cnt[co[c[t].x]]==0)
			ans--;
		if(++cnt[c[t].y]==1)
			ans++;
	}
	swap(co[c[t].x],c[t].y);
	//printf("%d use change %d: %d to %d,ans change to %d\n",i,t,c[t].x,c[t].y,ans);
}//计算每个修改对答案的影响
int main() {
	n=read(),m=read();
	len=pow(n,2.0/3);
	build();
	for(int i=1; i<=n; i++)
		co[i]=read();
	for(int i=1; i<=m; i++) {
		cin>>opt;
		if(opt=='Q') {
			++qn;
			q[qn].l=read(),q[qn].r=read();
			q[qn].pre=cn,q[qn].id=qn;
			//printf("%d %d\n",q[qn].l,q[qn].r);
		} else if(opt=='R') {
			++cn;
			c[cn].x=read(),c[cn].y=read();
		}
	}
	//printf("%d\n",q[1].id);
	sort(q+1,q+qn+1,cmp);
	//printf("%d\n",q[1].id);
	for(int i=1; i<=qn; i++) {
		//printf("%d\n",q[i].id);
		while (L < q[i].l) ans -= !--cnt[co[L++]];
		while (L > q[i].l) ans += !cnt[co[--L]] ++;
		while (R < q[i].r)ans += !cnt[co[++R]] ++;
		while (R > q[i].r) ans -= !--cnt[co[R --]];//从某位大佬那里学来的操作
		while(now<q[i].pre) work(++now,i);
		while(now>q[i].pre) work(now--,i);//六个 while 循环,前四个是普通莫队,后两个是带修专属
		tans[q[i].id]=ans;
		//puts("");
	}
	for(int i=1; i<=qn; i++)
		write(tans[i]),puts("");
	return 0;
}

原文地址:https://www.cnblogs.com/lajiccf/p/12903987.html