【模板】带修莫队

模板题

#include<bits/stdc++.h>
using namespace std;
int n,a[300005],pos[300005],m,sum[1000005],ans[2000005],t1,t2,a2[2000005][2],la[2000005],a3[1000005];
struct mzls
{
	int l,r,id,mo;
	bool operator<(const mzls &x)const
	{
		if(pos[l]!=pos[x.l])
			return pos[l]<pos[x.l];
		if(pos[r]!=pos[x.r])
			return pos[r]<pos[x.r];
		return mo<x.mo;
	}
}a1[2000005];
int main()
{
	scanf("%d%d",&n,&m);
	int d=pow(n,2.0/3);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		a3[i]=a[i];
		pos[i]=(i-1)/d;
	}
	for(int i=1;i<=m;i++)
	{
		char c1[5];
		scanf("%s",c1);
		if(c1[0]=='Q')
		{
			t1++;
			a1[t1].id=t1;
			scanf("%d%d",&a1[t1].l,&a1[t1].r);
			a1[t1].mo=t2;
		}
		else
		{
			t2++;
			scanf("%d%d",&a2[t2][0],&a2[t2][1]);
			la[t2]=a3[a2[t2][0]];
			a3[a2[t2][0]]=a2[t2][1];
		}
	}
	sort(a1+1,a1+t1+1);
	int x=0,l1=1,r1=0,tt=0;
	for(int i=1;i<=t1;i++)
	{
		while(r1>a1[i].r)
		{
			sum[a[r1--]]--;
			if(sum[a[r1+1]]==0)
				x--;
		}
		while(r1<a1[i].r)
		{
			sum[a[++r1]]++;
			if(sum[a[r1]]==1)
				x++;
		}
		while(l1>a1[i].l)
		{
			sum[a[--l1]]++;
			if(sum[a[l1]]==1)
				x++;
		}
		while(l1<a1[i].l)
		{
			sum[a[l1++]]--;
			if(sum[a[l1-1]]==0)
				x--;
		}
		while(tt<a1[i].mo)
		{
			tt++;
			if(a2[tt][0]>=l1&&a2[tt][0]<=r1)
			{
				sum[a2[tt][1]]++;
				if(sum[a2[tt][1]]==1)
					x++;
				sum[a[a2[tt][0]]]--;
				if(sum[a[a2[tt][0]]]==0)
					x--;
			}
			a[a2[tt][0]]=a2[tt][1];
		}
		while(tt>a1[i].mo)
		{
			if(a2[tt][0]>=l1&&a2[tt][0]<=r1)
			{
				sum[a2[tt][1]]--;
				if(sum[a2[tt][1]]==0)
					x--;
				sum[la[tt]]++;
				if(sum[la[tt]]==1)
					x++;
			}
			a[a2[tt][0]]=la[tt];
			tt--;
		}
		ans[a1[i].id]=x;
	}
	for(int i=1;i<=t1;i++)
		printf("%d\n",ans[i]);//
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值