【JZOJ4594】Dynamic len

###Description
有n个数编号从0→n-1,两种操作:
Q L R:询问编号为L→R-1的数中共有多少种不同的数
M X Y:将编号为X的数改为Y
共有m个操作

###Solution
把这题改对的过程我印象深刻。

我好想是拍了10次,一共拍了200+个数据,终于AC。

然后我看看别人的做法,代码量全都2000-,而我3000+。

好,不扯那么多了。

首先这题暴力可以拿30分。(废话)

然后我们考虑分块,当然这里从0开始十分的坑,要特别注意。

如何查询和修改呢?我们开两个数组 n e x t next next l a s t last last n e x t i next_i nexti表示下一个与当前位置的值相等的位置, l a s t i last_i lasti则相反。

这样,如果询问的 ( l , r ) (l,r) (l,r)这个区间(注意是这个区间,是 L → R − 1 L→R-1 LR1这个区间为 ( l , r ) (l,r) (l,r)),如果 n e x t i > r ( l ≤ i ≤ r ) next_i>r(l≤i≤r) nexti>r(lir)那么它的下一个相等的值都不在这个区间,可以直接统计答案。

然后,对于区间没有完全覆盖一个块的部分,直接暴力查询,对于覆盖整个块的部分,我们对每个块以 n e x t i next_i nexti为关键字排序,得到一个 n e x t i next_i nexti单调不减的块,然后我们对于这些块,二分一个最大的 p p p使得 a p ≤ r a_p≤r apr,然后显然这个块 p + 1 p+1 p+1后的都是满足 n e x t i > r next_i>r nexti>r,直接统计进答案即可。

简单来说就是下图:
这里写图片描述

如果你看到这觉得懵逼了,你可以去打带修改莫队算法(简单,粗暴,250)。

这就结束了吗?

我们还有修改操作!!怎么办?!

修改的操作一样简单。我们只要改变上一次相等值的 n e x t next next,还有下一次相等值的 l a s t last last,然后把新的值加进来的 n e x t next next l a s t last last修改,然后重新对有修改的块重新排序,就可以了。

怎么找一个新的值的 n e x t next next l a s t last last

我们开一个数组 S i , j S_{i,j} Si,j表示第 i i i个块, j j j这个数出现了多少次。

于是我们发现要离散化,直接按顺序标号即可。

还有一个与该题类似的题:

【2011集训队出题】数颜色

###Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 50001
#define M 1000001
#define _N 250
using namespace std;
int a[N];
int map[M];
int tot=0;
struct node{
	int l,r;
	int z[_N],px[_N];
}b[_N];
bool bz[N*2];
int zz[N*2];
int next[N],last[N];
int s[_N][N*2];
int pos[N];
bool cmp(int x,int y)
{
	return next[x]<next[y];
}
int main()
{
	freopen("1942.in","r",stdin);
	freopen("1942.out","w",stdout);
	int n,m;
	cin>>n>>m;
	fo(i,0,n-1)
	{
		scanf("%d",&a[i]);
		if(!map[a[i]]) map[a[i]]=++tot;
		a[i]=map[a[i]];
	}
	memset(zz,-1,sizeof(zz));
	fo(i,0,n-1)
	{
		next[i]=n;
		last[i]=i;
		if(zz[a[i]]<0) zz[a[i]]=i;
		else
		{
			last[i]=zz[a[i]];
			next[last[i]]=i;
			zz[a[i]]=i;
		}
	}
	int t=int(sqrt(n));
	int l=0,r=t-1;
	int mxn=n/t+1;
	fo(i,1,n/t+1)
	{
		b[i].l=l,b[i].r=r;
		int cnt=0;
		fo(j,l,r)
		{
			pos[j]=i;
			s[i][a[j]]++;
			b[i].z[++cnt]=b[i].px[cnt]=j;
		}
		sort(b[i].px+1,b[i].px+r-l+2,cmp);
		l=r+1;
		r=min(l+t-1,n-1);
	}
	while(m--)
	{
		char ch[5];
		int x,y;
		scanf("%s %d %d",ch,&x,&y);
		if(ch[0]=='Q')
		{
			x--;y--;
			int ans=0;
			int l=pos[x],r=pos[y];
			if(l==r)
			{
				fo(i,x,y)
				if(next[i]>y) ans++;
				printf("%d\n",ans);
				continue;
			}
			if(x>b[l].l)
			{
				fo(i,x,b[l].r)
				if(next[i]>y) ans++;
				l++;
			}
			if(y<b[r].r)
			{
				fo(i,b[r].l,y)
				if(next[i]>y) ans++;
				r--;
			}
			fo(i,l,r)
			{
				int ll=0,rr=b[i].r-b[i].l+1;
				while(ll<rr-1)
				{
					int mid=(ll+rr)/2;
					if(next[b[i].px[mid]]<=y) ll=mid;
					else rr=mid; 
				}
				int q;
				if(next[b[i].px[rr]]<=y) q=rr;
				else q=ll;
				ans+=b[i].r-b[i].l-q+1;
			}
			printf("%d\n",ans);
		}
		else
		{
			x--;
			if(!map[y]) map[y]=++tot;
			y=map[y];
			next[last[x]]=next[x];
			int tt=pos[last[x]];
			sort(b[tt].px+1,b[tt].px+b[tt].r-b[tt].l+2,cmp);
			if(last[x]==x) last[next[x]]=next[x];
			else last[next[x]]=last[x];
			int l=pos[x],r=pos[x];
			s[l][a[x]]--;
			next[x]=n;
			last[x]=x;
			bool tf=false;
			fd(i,x-1,b[l].l)
			if(a[b[l].z[i-b[l].l+1]]==y)
			{
				last[x]=i;
				next[i]=x;
				tf=true;
				break;
			}
			if(!tf)
			{
				fd(i,l-1,1)
				if(s[i][y])
				{
					fd(j,b[i].r,b[i].l)
					if(a[b[i].z[j-b[i].l+1]]==y)
					{
						last[x]=j;
						next[j]=x;
						sort(b[i].px+1,b[i].px+b[i].r-b[i].l+2,cmp);
						tf=true;
						break;
					}
					if(tf) break;
				}
			}
			tf=false;
			fo(i,x+1,b[l].r)
			if(a[b[l].z[i-b[l].l+1]]==y)
			{
				next[x]=i;
				last[i]=x;
				tf=true;
				break;
			}
			if(!tf)
			{
				fo(i,r+1,mxn)
				if(s[i][y])
				{
					fo(j,b[i].l,b[i].r)
					if(a[b[i].z[j-b[i].l+1]]==y)
					{
						next[x]=j;
						last[j]=x;
						tf=true;
						break;
					}
					if(tf) break;
				}
			}
			a[x]=y;
			s[l][y]++;
			sort(b[l].px+1,b[l].px+b[l].r-b[l].l+2,cmp);
		}
	}
}
posted @ 2020-12-23 18:45  sadstone  阅读(61)  评论(0编辑  收藏  举报