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

题链

1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。

2、 R P Col 把第P支画笔替换为颜色Col。

带修改莫队;

学玩普通莫队再看带修改莫队,OI-wiki上讲的通俗易懂;

对比主要是这几点:

1.分块unit = pow(n,2.0/3.0);

2.对询问排序是先排左区间是否在同一个块,再排右区间,然后是时间

3.将询问和修改划分成两个数组,莫队将左右指针移动到询问区间过后再考虑修改问题,已知本次询问的time,然后在修改数组上将time之前的修改都跑一遍,其中修改值与被修改值是swap相互替换,因为可能要回退,也就是换回来。

#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define Pair pair<LL,LL>
#define ls rt<<1
#define rs rt<<1|1
#define Pi acos(-1.0)
#define eps 1e-6
#define DBINF 1e100
#define mod 1000000007
#define MAXN 1e18
#define MS 1000009

LL n,m;
int a[MS];
struct node{
	int l,r,id;
}ask[MS];
int asknum;
int unit;

struct nod{
	int pos,tar,id;
}alt[MS];
int altnum;

int v[MS];

int ac[MS]; 

bool cmp(node t1,node t2){
	if(t1.l/unit != t2.l/unit) return t1.l < t2.l;
	if(t1.r/unit != t2.r/unit) return t1.r < t2.r;
	return t1.id < t2.id;
}

int main() {
	ios::sync_with_stdio(false);
	cin >> n >> m;
	for(int i=1;i<=n;i++){
		cin >> a[i];
	}
	for(int i=1;i<=m;i++){
		char op;
		cin >> op;
		if(op == 'Q'){
			int l,r;
			cin >> l >> r;
			ask[++asknum] = {l,r,i};
		}
		else if(op == 'R'){
			int pos,tar;
			cin >> pos >> tar;
			alt[++altnum] = {pos,tar,i};
		}
	}
	unit = pow(n,2.0/3.0);
	sort(ask+1,ask+asknum+1,cmp);
	int ans = 0;
	int L = 1 ,R = 0;
	int time = 0;
	for(int i=1;i<=asknum;i++){
		int l = ask[i].l;
		int r = ask[i].r;
		int id = ask[i].id;
		while(L < l){
			v[a[L]]--;
			if(v[a[L]] == 0) ans--;
			L++;
		}
		while(L > l){
			L--;
			v[a[L]]++;
			if(v[a[L]] == 1) ans++;
		}
		while(R < r){
			R++;
			v[a[R]]++;
			if(v[a[R]] == 1) ans++;
		}
		while(R > r){
			v[a[R]]--;
			if(v[a[R]] == 0) ans--;
			R--;
		}
		
		while(alt[time+1].id < id && time+1 <= altnum){
			time++;
			int altpos = alt[time].pos;
			int alttar = alt[time].tar;
			if(L <= altpos && altpos <= R){
				v[a[altpos]]--;
				if(v[a[altpos]] == 0) ans--;
				swap(a[altpos],alt[time].tar);
				v[a[altpos]]++;
				if(v[a[altpos]] == 1) ans++;
			}
			else{
				swap(a[altpos],alt[time].tar);
			}
		}
		while(alt[time].id > id){
			int altpos = alt[time].pos;
			int alttar = alt[time].tar;
			if(L <= altpos && altpos <= R){
				v[a[altpos]]--;
				if(v[a[altpos]] == 0) ans--;
				swap(a[altpos],alt[time].tar);
				v[a[altpos]]++;
				if(v[a[altpos]] == 1) ans++;
			}
			else{
				swap(a[altpos],alt[time].tar);
			}
			time--;
		}
		
		ac[ask[i].id] = ans;
		
	}
	
	for(int i=1;i<=m;i++){
		if(ac[i]){
			cout << ac[i] << "\n";
		}
	}
	

	return 0;
}
posted @ 2021-05-07 20:38  棉被sunlie  阅读(58)  评论(0)    收藏  举报