bzoj 2120:数颜色(单点修改莫队)

在这里插入图片描述


普通不带修改的莫队是对询问二元组 ( l , r ) (l,r) 进行分块排序以降低复杂度

对于单点修改的莫队,引入一个时间坐标 t,询问变成三元组: ( l , r , t ) (l,r,t)

每一步 ( l , r , t ) (l,r,t) 有6个方向可走

用类似普通莫队的分块方法,对 l,r 以 n 2 3 n^{\frac{2}{3}} 的大小进行分块,可以证明复杂度为 n 5 3 n^{\frac{5}{3}} ,对 1 0 4 10^4 的数据还比较快

对于更新修改操作,只需要维护一个栈,按栈序撤销即可。

参考博客


#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int block,n,m,tot,top;
#define pii pair<int,int>
#define fir first
#define sec second
struct node{
	int id,l,r,t;
	node(int idi = 0,int li = 0,int ri = 0,int ti = 0) {
		id = idi;
		l = li;
		r = ri;
		t = ti;
	}
	bool operator < (const node &rhs) const {
		if(l / block != rhs.l / block) return l < rhs.l;
		if(r / block != rhs.r / block) return r < rhs.r;
		return t < rhs.t;
	}
}q[maxn];
struct ss {
	int t,x,y;
	ss(int ti = 0,int xi = 0,int yi = 0) {
		t = ti;
		x = xi;
		y = yi;
	}
}op[maxn];
char s[maxn];
int a[maxn],curleft,curright,curtime,vis[maxn],res,ans[maxn];
vector<pii> sta;
void modify(int l,int r,int t) {
	while(curtime < t) {
		curtime++;
		if(op[curtime].t == 1) {
			int x = op[curtime].x, y = op[curtime].y;
			sta.push_back(pii(x,a[x]));
			if(curleft <= x && x <= curright)  {
				vis[a[x]]--;
				if(vis[a[x]] == 0) res--;
			}
			a[x] = y;
			if(curleft <= x && x <= curright)  {
				vis[a[x]]++;
				if(vis[a[x]] == 1) res++;
			}
		}
	}
	while(curtime > t) {
		if(op[curtime].t == 1) {
			pii tp = sta.front();
			sta.pop_back();
			if(curleft <= tp.fir && tp.fir <= curright) {
				vis[a[tp.fir]]--;
				if(vis[a[tp.fir]] == 0) res--;
			}
			a[tp.fir] = tp.sec;
			if(curleft <= tp.fir && tp.fir <= curright)
				vis[a[tp.fir]]++;
				if(vis[a[tp.fir]] == 1) res++;
		}
		curtime--;
	}
	while(curleft < l) {
		vis[a[curleft]]--;
		if(vis[a[curleft]] == 0) res--;
		curleft++;
	}
	while(curleft > l) {
		curleft--;
		vis[a[curleft]]++;
		if(vis[a[curleft]] == 1) res++;
	}
	while(curright < r) {
		curright++;
		vis[a[curright]]++;
		if(vis[a[curright]] == 1) res++;
	}
	while(curright > r) {
		vis[a[curright]]--;
		if(vis[a[curright]] == 0) res--;
		curright--;
	}
}
int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++)
		scanf("%d",&a[i]);
	for(int i = 1,x,y; i <= m; i++) {
		scanf("%s%d%d",s,&x,&y);
		if(s[0] == 'Q') q[++tot] = node(tot,x,y,i),op[i] = ss(0,x,y);
		else op[i] = ss(1,x,y);
	}
	block = min(500,n);
	sort(q + 1,q + tot + 1);
	res = curleft = curright = curtime = 0;
	for(int i = 1; i <= tot; i++) {
		modify(q[i].l,q[i].r,q[i].t);
		ans[q[i].id] = res;
	}
	for(int i = 1; i <= tot; i++)
		printf("%d\n",ans[i]);
	return 0;
}
发布了332 篇原创文章 · 获赞 10 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_41997978/article/details/104101418