【BZOJ2120】带修改莫队模板

BZOJ2120

普通莫队一般是不带修改的,但是有一些题目是需要修改的…
比如BZOJ2120。
这题如果没有修改,那大概就是个莫队裸题,但是它现在带修改了,就需要一些操作了。
我们把对于询问的结构体记录一个上一次的修改,例如第5次询问是在第3次修改之后进行的。
那么如果我们需要询问第5次询问,现在修改还在第1次,我们就把修改改成2,3次之后,再进行询问就可以了。思想上还是莫队。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6+7;
int n,m,qnum,cnum,block,Ans = 0;
int a[maxn],b[maxn],cnt[maxn],ans[maxn];
struct node
{
	int x,y,pre,id;
	bool operator<(const node &rhs)const
	{
		if(b[x]!=b[rhs.x]) return b[x]<b[rhs.x];
		if(b[y]!=b[rhs.y]) return b[y]<b[rhs.y];
		return pre<rhs.pre;
	}
}Q[maxn];
struct change
{
	int pos,x;
}C[maxn];
void add(int x)
{
	if(++cnt[x]==1) Ans++;
}
void del(int x)
{
	if(--cnt[x]==0) Ans--;
}
void gao(int now,int o)
{
	if(Q[o].x<=C[now].pos && Q[o].y>=C[now].pos)
	{
		if(--cnt[a[C[now].pos]]==0) Ans--;
		if(++cnt[C[now].x]==1) Ans++;
	}
	swap(a[C[now].pos],C[now].x);
}
void solve()
{
	int l = 1,r = 0,now = 0;
	for(int i=1;i<=qnum;i++)
	{
		while(l<Q[i].x) del(a[l++]);
		while(l>Q[i].x) add(a[--l]);
		while(r<Q[i].y) add(a[++r]);
		while(r>Q[i].y) del(a[r--]);
		while(now<Q[i].pre) gao(++now,i);
		while(now>Q[i].pre) gao(now--,i);
		ans[Q[i].id] = Ans;
	}
	for(int i=1;i<=qnum;i++) printf("%d\n",ans[i]);
}
int main()
{
	scanf("%d%d",&n,&m);
	block = sqrt(n*2.0/3.0);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",a+i);
		b[i] = i/block+1;
	}
	for(int i=0;i<m;i++)
	{
		char op[5];
		scanf("%s",op);
		if(op[0]=='Q')
		{
			int l,r;
			scanf("%d%d",&l,&r);
			Q[++qnum].x = l;
			Q[qnum].y = r;
			Q[qnum].pre = cnum;
			Q[qnum].id = qnum;
		}
		else if(op[0]=='R')
		{
			int x,y;
			scanf("%d%d",&x,&y);
			C[++cnum].pos = x;
			C[cnum].x = y;
		}
	}
	sort(Q+1,Q+1+qnum);
	solve();
	return 0;
}
发布了159 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KIKO_caoyue/article/details/101049887