求助分块
查看原帖
求助分块
132533
FutaRimeWoawaSete楼主2021/5/2 20:39

怀疑是单独块出了问题。

WA。

有对拍器的话也可以发给我

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int Len = 1e5 + 5 , SIZE = 330;
int n,m,fr[SIZE][Len],col[Len],fa[Len],cnt[SIZE][Len],sum[SIZE][SIZE],vt,t,L[SIZE],R[SIZE],pos[Len],VL[SIZE],VR[SIZE],Vpos[Len],a[Len];
void makeSet(int x){for(int i = 1 ; i <= x ; i ++) fa[i] = i;}
int findSet(int x){return fa[x] == x ? fa[x] : fa[x] = findSet(fa[x]);}
inline void merge(int x,int X,int Y)
{
	if(!fr[x][X]) return;
	else if(!fr[x][Y]){fr[x][Y] = fr[x][X] , col[fr[x][Y]] = Y;}
	else fa[fr[x][X]] = fr[x][Y];
	fr[x][X] = 0;
}
inline void build(int x,int l,int r,int X,int Y)
{
	for(int i = L[x] ; i <= R[x] ; i ++){a[i] = col[findSet(i)] ; fr[x][a[i]] = 0;}
	for(int i = l ; i <= r ; i ++) if(a[i] == X) a[i] = Y;
	for(int i = L[x] ; i <= R[x] ; i ++) 
	{
		if(!fr[x][a[i]]){fr[x][a[i]] = i;col[fr[x][a[i]]] = a[i];}
		fa[i] = fr[x][a[i]];
	}
}
inline void upd(int l,int r,int X,int Y)
{
	if(X == Y) return;
	int LL = pos[l] , RR = pos[r];
	int numb = 0 , Tmp = 0;
	if(LL == RR) 
	{
		for(int i = l ; i <= r ; i ++) if(col[findSet(i)] == X) numb ++;
		for(int i = LL ; i <= t ; i ++) sum[i][Vpos[X]] -= numb , sum[i][Vpos[Y]] += numb , cnt[i][X] -= numb , cnt[i][Y] += numb;
		build(LL , l , r , X , Y);
		return;
	}
	for(int i = l ; i <= R[LL] ; i ++) if(col[findSet(i)] == X) numb ++;
	for(int i = LL + 1 ; i <= RR - 1 ; i ++) numb += Tmp , sum[i][Vpos[X]] -= numb , sum[i][Vpos[Y]] += numb , Tmp = cnt[i + 1][X] - cnt[i][X] , cnt[i][X] -= numb , cnt[i][Y] += numb; 
	for(int i = L[RR] ; i <= r ; i ++) if(col[findSet(i)] == X) numb ++;
	for(int i = RR ; i <= t ; i ++) sum[i][Vpos[X]] -= numb , sum[i][Vpos[Y]] += numb , cnt[i][X] -= numb , cnt[i][Y] += numb; 
	for(int i = LL + 1 ; i <= RR - 1 ; i ++) merge(i , X , Y);
	build(LL , l , R[LL] , X , Y);
	build(RR , L[RR] , r , X , Y);
	return;
}
int UsedSum[Len],UsedBlock[SIZE];
inline int qry(int l,int r,int k)
{
	int LL = pos[l] , RR = pos[r];
	if(k > r - l + 1) return -1;
	if(LL == RR)
	{
		for(int i = l ; i <= r ; i ++) UsedBlock[Vpos[col[findSet(i)]]] ++ , UsedSum[col[findSet(i)]] ++;
		for(int j = 1 ; j <= vt ; j ++) 
		{
			if(k > UsedBlock[j]) k -= UsedBlock[j];
			else
			{
				for(int p = VL[j] ; p <= VR[j] ; p ++) 
				{
					if(k > UsedSum[p]) k -= UsedSum[p];
					else 
					{
						for(int i = l ; i <= r ; i ++) UsedBlock[Vpos[col[findSet(i)]]] -- , UsedSum[col[findSet(i)]] --;
						return p;
					}
				}
			}
		}
	}
	for(int i = l ; i <= R[LL] ; i ++) UsedBlock[Vpos[col[findSet(i)]]] ++ , UsedSum[col[findSet(i)]] ++;
	for(int i = L[RR] ; i <= r ; i ++) UsedBlock[Vpos[col[findSet(i)]]] ++ , UsedSum[col[findSet(i)]] ++;
	for(int j = 1 ; j <= vt ; j ++)
	{
		if(k > (sum[RR - 1][j] - sum[LL][j] + UsedBlock[j])) k -= sum[RR - 1][j] - sum[LL][j] + UsedBlock[j];
		else
		{
			for(int p = VL[j] ; p <= VR[j] ; p ++)
			{
				if(k > (cnt[RR - 1][p] - cnt[LL][p] + UsedSum[p])) k -= cnt[RR - 1][p] - cnt[LL][p] + UsedSum[p];
				else 
				{
					for(int i = l ; i <= R[LL] ; i ++) UsedBlock[Vpos[col[findSet(i)]]] -- , UsedSum[col[findSet(i)]] --;
					for(int i = L[RR] ; i <= r ; i ++) UsedBlock[Vpos[col[findSet(i)]]] -- , UsedSum[col[findSet(i)]] --;
					return p;
				}
			}
		}
	}
}
signed main()
{
	int maxn = 0;
	scanf("%d %d",&n,&m);
	makeSet(n);
	t = sqrt(n);
	for(int i = 1 ; i <= n ; i ++){scanf("%d",&a[i]) ; maxn = max(maxn , a[i]);}
	vt = sqrt(maxn);
	for(int i = 1 ; i <= t ; i ++) L[i] = (i - 1) * t + 1 , R[i] = i * t;
	R[t] = n;
	for(int i = 1 ; i <= vt ; i ++) VL[i] = (i - 1) * vt + 1 , VR[i] = i * vt;
	VR[vt] = maxn;
	for(int i = 1 ; i <= t ; i ++) 
		for(int j = L[i] ; j <= R[i] ; j ++) pos[j] = i;
	for(int i = 1 ; i <= vt ; i ++) 
		for(int j = VL[i] ; j <= VR[i] ; j ++) Vpos[j] = i;
	for(int i = 1 ; i <= t ; i ++)
	{
		for(int j = L[i] ; j <= R[i] ; j ++)
		{
			if(!fr[i][a[j]]){fr[i][a[j]] = j ; col[fr[i][a[j]]] = a[j];}
			fa[j] = fr[i][a[j]];
			cnt[i][a[j]] ++ , sum[i][Vpos[a[j]]] ++;
		}
		for(int j = 1 ; j <= vt ; j ++) sum[i][j] += sum[i - 1][j];
		for(int j = 1 ; j <= maxn ; j ++) cnt[i][j] += cnt[i - 1][j]; 
	}
	for(int i = 1 ; i <= m ; i ++)
	{
		int opt,l,r,x,y;scanf("%d %d %d %d",&opt,&l,&r,&x);
		if(opt == 1){scanf("%d",&y);upd(l , r , x , y);}
		else printf("%d\n",qry(l , r , x));
	}
	return 0;
}
2021/5/2 20:39
加载中...