Ynoi2018 未来日记

link\color{deeppink}link

  1. 1 l r x y 把区间 [l,r][l,r] 中的 xx 变成 yy
  2. 2 l r k 查找区间 [l,r][l,r] 中第 kk 小值

分块儿,考虑 II 为块的编号,ii 为序列中或值的编号。

将值域和序列分块,令 cnt[I][val]cnt[I][val] 表示在前 II 块中值是 valval 中的个数,

valcnt[I][VAL]valcnt[I][VAL] 表示在前 II 块中值在 VALVAL 中的个数。

对于 query(l,r,k)query(l,r,k),考虑先把答案的块求出来。

令不在整块中的元素集为 PP,求出 Pcnt[VAL]Pcnt[VAL] 表示 PP 中值域在 VALVAL 元素的元素个数。

则有:

I=1ANSPcnt[I]+valcnt[R][I]valcnt[L1][I]k\sum_{I=1}^{ANS}Pcnt[I]+valcnt[R][I]-valcnt[L-1][I]\ge k

11 开始枚举即可。

而后考虑具体地求出答案。

又令 pcnt[val]pcnt[val] 表示在 PP 中,valval 的个数,则有:

i=1ans=pcnt[i]+cnt[R][i]cnt[L1][i]krest\sum_{i=1}^{ans}=pcnt[i]+cnt[R][i]-cnt[L-1][i]\ge k-\text{rest}

rest 就是值域在 [1,ANS][1,ANS] 中的元素个数。

接下来就是修改了。

对于某一个块,维护 faxfa_x 表示值 xx 在并查集中对应的第一个的位置,valxval_x 表示 xx 位置对应的值,posx=faaxpos_x=fa_{a_x}

则对于 ii 位置的权值即为 valposival_{pos_i}

有以下情况:

  • xx

跳过。

  • xxyy

fay=fax,valfax=y,fax=0fa_y=fa_x,val_{fa_x}=y,fa_x=0

  • x,yx,y

注意到所有的权值最多有 n+mn+m 个,而这种情况会少一个权值,故可以暴力重构,时间是 O((n+m)n)O((n+m)\sqrt n)

修改的时候把每一个块从头枚举一遍即可,顺便修改下 cntcnt 一类的值即可。

复杂的是优秀的 O((n+m)n)O((n+m)\sqrt n)

//#pragma GCC optimize("O2")
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+50,M=N/500+50;

int n,b[N],q,ed[N],bg[N],belong[N],a[N],siz=500,mx,cnt[M][N],valcnt[M][M],Pcnt[M],pcnt[N],fa[M][N],pos[N],val[N];

void change(int l,int r,int x,int y)
{
	int s=0,nx=cnt[belong[l]][x];
	if(belong[l]==belong[r])
	{
		for(int i=bg[belong[l]];i<=ed[belong[l]];i++)
		{
			fa[belong[l]][val[i]]=0,a[i]=val[pos[i]];
		}
		for(int i=l;i<=r;i++)if(a[i]==x)a[i]=y,++s;
		for(int i=bg[belong[l]];i<=ed[belong[l]];i++)
		{
			fa[belong[l]][a[i]]=(fa[belong[l]][a[i]]?fa[belong[l]][a[i]]:i);
			pos[i]=fa[belong[l]][a[i]];val[i]=a[i];
		}
		for(int i=belong[l];i<=belong[n];i++)
		{
			valcnt[i][belong[x]]-=s;
			valcnt[i][belong[y]]+=s;
			cnt[i][x]-=s;
			cnt[i][y]+=s;
		}
		return;
	}
	if(fa[belong[l]][x])
	{
		for(int i=bg[belong[l]];i<=ed[belong[l]];i++)
		{
			fa[belong[l]][val[i]]=0,a[i]=val[pos[i]];
		}
		for(int i=l;i<=min(ed[belong[l]],r);i++)if(a[i]==x)a[i]=y,++s;
		for(int i=bg[belong[l]];i<=ed[belong[l]];i++)
		{
			fa[belong[l]][a[i]]=(fa[belong[l]][a[i]]?fa[belong[l]][a[i]]:i);
			pos[i]=fa[belong[l]][a[i]];val[i]=a[i];
		}
		valcnt[belong[l]][belong[x]]-=s;
		valcnt[belong[l]][belong[y]]+=s;
		cnt[belong[l]][x]-=s;
		cnt[belong[l]][y]+=s;
	}
	for(int i=belong[l]+1;i<belong[r];i++)
	{
		if(!fa[i][x])
		{
			valcnt[i][belong[x]]-=s;
			valcnt[i][belong[y]]+=s;
			cnt[i][x]-=s;
			cnt[i][y]+=s;
			continue;
		}
		if(!fa[i][y])
		{
			fa[i][y]=fa[i][x];
			val[fa[i][x]]=y;
			fa[i][x]=0;
		}
		else
		{
			for(int j=bg[i];j<=ed[i];j++)
			{
				a[j]=val[pos[j]];
				fa[i][val[j]]=0;
				if(a[j]==x)a[j]=y;
			}
			for(int j=bg[i];j<=ed[i];j++)
			{
				fa[i][a[j]]=(fa[i][a[j]]?fa[i][a[j]]:j);
				pos[j]=fa[i][a[j]];val[j]=a[j];
			}
		}
		s+=cnt[i][x]-nx;nx=cnt[i][x];
		valcnt[i][belong[x]]-=s;
		valcnt[i][belong[y]]+=s;
		cnt[i][x]-=s;
		cnt[i][y]+=s;
	}
	if(fa[belong[r]][x])
	{
		for(int i=bg[belong[r]];i<=ed[belong[r]];i++)
		{
			fa[belong[r]][val[i]]=0,a[i]=val[pos[i]];
		}
		for(int i=bg[belong[r]];i<=r;i++)if(a[i]==x)a[i]=y,++s;
		for(int i=bg[belong[r]];i<=ed[belong[r]];i++)
		{
			fa[belong[r]][a[i]]=(fa[belong[r]][a[i]]?fa[belong[r]][a[i]]:i);
			pos[i]=fa[belong[r]][a[i]];val[i]=a[i];
		}
	}
	for(int i=belong[r];i<=belong[n];i++)
	{
		valcnt[i][belong[x]]-=s;
		valcnt[i][belong[y]]+=s;
		cnt[i][x]-=s;
		cnt[i][y]+=s;
	}
}

void find(int l,int r,int k)
{
	if(belong[l]==belong[r])
	{
		for(int i=l;i<=r;i++)b[i-l+1]=val[pos[i]];
		sort(b+1,b+1+r-l+1);printf("%ld\n",b[k]);return;
	}
	for(int i=1;i<=belong[n];i++)Pcnt[i]=0;
	for(int i=l;i<=ed[belong[l]];i++)++Pcnt[belong[val[pos[i]]]];
	for(int i=bg[belong[r]];i<=r;i++)++Pcnt[belong[val[pos[i]]]];
	int re=0,u=0;
	while(++u)
	{
		if(re+Pcnt[u]+valcnt[belong[r]-1][u]-valcnt[belong[l]][u]>=k)break;
		re+=Pcnt[u]+valcnt[belong[r]-1][u]-valcnt[belong[l]][u];
	}
	for(int i=bg[u];i<=ed[u];i++)pcnt[i]=0;
	for(int i=l;i<=ed[belong[l]];i++)++pcnt[val[pos[i]]];
	for(int i=bg[belong[r]];i<=r;i++)++pcnt[val[pos[i]]];
	for(int i=bg[u];i<=ed[u];i++)
	{
		re+=pcnt[i]+cnt[belong[r]-1][i]-cnt[belong[l]][i];
		if(re>=k){printf("%ld\n",i);return;}
	}
}

char cch,B0[1<<15],*S=B0,*TT=B0;
#define getc() (S==TT&&(TT=(S=B0)+fread(B0,1,1<<15,stdin),S==TT)?0:*S++)
int aa;inline int read(){
	while(cch=getc(),cch<'0'||cch>'9');aa=cch-'0';
	while(cch=getc(),cch>='0'&&cch<='9')aa=((aa<<3)+(aa<<1))+cch-'0';return aa;
}

main()
{
//	freopen("data.txt","r",stdin);
//	freopen("wa.txt","w",stdout);
	n=read(),q=read();
	for(int i=1;i<=n;i++)a[i]=read();
	for(int i=1;i<=n;i++)belong[i]=(i-1)/siz+1;
	for(int i=1;i<=belong[n];i++)
	{
		bg[i]=((i-1)*siz+1),ed[i]=(i*siz);
		for(int j=1;j<=n;j++)cnt[i][j]=cnt[i-1][j];
		for(int j=1;j<=belong[n];j++)valcnt[i][j]=valcnt[i-1][j];
		for(int j=bg[i];j<=ed[i];j++)cnt[i][a[j]]++,valcnt[i][belong[a[j]]]++;
		for(int j=bg[i];j<=ed[i];j++)
		{
			if(!fa[i][a[j]])fa[i][a[j]]=j;
			pos[j]=fa[i][a[j]];val[j]=a[j];
		}
	}
	while(q--)
	{
		int opt,l,r,k,x,y;
		opt=read(),l=read(),r=read();
		if(opt==1)
		{
			x=read(),y=read();
			if(x==y)continue;
			change(l,r,x,y);
		}
		else
		{
			k=read();
			find(l,r,k);
		}
	}
}