On block interval mode

preface

Block method is good(

This article directly talks about examples qwq

P4168 [Violet] dandelion

Title Link: P4168 [Violet] dandelion

Meaning: find the mode with the smallest number in the interval and force online

Solution I

Direct blocking

Set the block length as l e n len len, the total number of blocks is t t t

We first preprocess all interval modes and the number of occurrences of modes with the endpoint of the block as the endpoint

In other words, the minimum mode of number and its occurrence times are calculated for the interval composed of each continuous block

Don't forget to discretize, or MLE

Total t 2 t^2 t2 such intervals are processed each time O ( n ) O(n) O(n), then the preprocessing time complexity is O ( n t 2 ) O(nt^2) O(nt2)

When querying, you can temporarily update the array based on the preprocessed array to count the answers, and then restore the array

Total time complexity O ( n t 2 + m n / t ) O(nt^2+mn/t) O(nt2+mn/t)

hypothesis m m m and n n n of the same order of magnitude, solution n t 2 = m n / t nt^2=mn/t nt2=mn/t, t ≈ n 3 t \approx \sqrt[3]{n} t≈3n ​

Then the time complexity can be controlled within O ( n 5 / 3 ) O(n^{5/3}) In O(n5/3)

The space complexity is relatively large, O ( n t 2 ) O(nt^2) O(nt2) (Note: required for pretreatment)

The code is as follows

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN (int)(5e4+5)
#define MAXM (int)(45)
#define pc(a) putchar(a)
template<typename T>inline void read(T &k)
{
	char ch=getchar();T x=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	k=x*f;
}
template<typename T>void write(T k)
{
	if(k<0){pc('-');k=-k;}
	if(k>9)write(k/10);
	pc(k%10+'0');
}
int n,m,Q,len,last,t;
int id[MAXN],L[MAXN],R[MAXN],c[MAXM][MAXM][MAXN]; // c[i][j][a[k]] indicates the number of occurrences of a[k] in blocks i~j
int b[MAXN],f[MAXM][MAXM][2],now[2],a[MAXN]; // f[i][j][0/1] record the times and modes respectively
void init()
{
    // Pretreatment
	sort(b+1,b+1+n);
	m=unique(b+1,b+1+n)-b-1;
	for(int i=1; i<=n; i++)
		a[i]=lower_bound(b+1,b+1+m,a[i])-b; // Discretization
	t=pow((double)n,(double)1/3); // Number of blocks
	len=t?n/t:n; // Length of block
	for(int i=1; i<=t; i++)
	{
		L[i]=(i-1)*len+1;
		R[i]=i*len;
	}
	if(R[t]<n)
	{
		L[t+1]=R[t]+1;
		R[++t]=n;
	}
	for(int i=1; i<=t; i++)
		for(int j=L[i]; j<=R[i]; j++)
			id[j]=i;
	for(int i=1; i<=t; i++)
		for(int j=i; j<=t; j++)
		{
			for(int k=L[i]; k<=R[j]; k++)
				++c[i][j][a[k]]; // Statistical answer
			for(int k=1; k<=m; k++)
			{
				if(c[i][j][k]>f[i][j][0]) // Update answer
				{
					f[i][j][0]=c[i][j][k];
					f[i][j][1]=k;
				}
			}
		}
}
void proc(int x,int y,int k)
{
	++c[x][y][k]; // Temporary modification
	if(c[x][y][k]>now[0]||c[x][y][k]==now[0]&&k time<now[1])
	{
		now[0]=c[x][y][k]; // Update answer
		now[1]=k;
	}
}
void solve(int l,int r)
{
	l=(l+last-1)%n+1; // Title Requirements
	r=(r+last-1)%n+1;
	if(l>r)swap(l,r); // Title Requirements

	int p=id[l],q=id[r],x=0,y=0;
	if(p+1<=q-1)x=p+1,y=q-1;
	memcpy(now,f[x][y],sizeof(now));
	if(p==q)
	{
		for(int i=l; i<=r; i++)proc(x,y,a[i]); // Temporary modification + update answer
		for(int i=l; i<=r; i++)--c[x][y][a[i]]; // Change back
	}else
	{
		for(int i=l; i<=R[p]; i++)proc(x,y,a[i]);
		for(int i=L[q]; i<=r; i++)proc(x,y,a[i]);
		for(int i=l; i<=R[p]; i++)--c[x][y][a[i]];
		for(int i=L[q]; i<=r; i++)--c[x][y][a[i]];
	}
	write(last=b[now[1]]);pc('\n');
}
signed main()
{
	read(n);read(Q);
	for(int i=1; i<=n; i++)
		read(a[i]),b[i]=a[i];
	init();
	while(Q--)
	{
		int l,r;
		read(l);read(r);
		solve(l,r);
	}
	return 0;
}

Solution II

It's still divided into blocks, but the maintenance things are different

We find that the space of solution one is mostly in the number of times statistics

Frequency statistics? Can't you give two points?

Create a vector for each value and save its subscript. The number of occurrences is upper_bd-lower_bd

So we just need to preprocess who the mode is

Just compare the violence query result with the mode result

Don't forget to discretize

It's a little time to change space, but it's still very fast

Time complexity O ( n t + m n / t × log ⁡ n ) O(nt+mn/t\times \log n) O(nt+mn/t×logn)

hypothesis m m m and n n n is the same order of magnitude, or solve the equation, t ≈ n log ⁡ n t \approx \sqrt{n\log n} t≈nlogn ​

Then the time complexity can be controlled within O ( n n log ⁡ n ) O(n\sqrt{n\log n}) O(nnlogn ​)

Spatial complexity O ( t 2 ) O(t^2) O(t2), good

The code is as follows

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN (int)(5e4+5)
#define MAXM (int)(888)
#define pc(a) putchar(a)
template<typename T>inline void read(T &k)
{
	char ch=getchar();T x=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	k=x*f;
}
template<typename T>void write(T k)
{
	if(k<0){pc('-');k=-k;}
	if(k>9)write(k/10);
	pc(k%10+'0');
}
int n,m,Q,last,t,len,c[MAXN],id[MAXN];
int a[MAXN],b[MAXN],L[MAXM],R[MAXM],f[MAXM][MAXM];
vector<int> vec[MAXN];
int find(int k,int l,int r)
{
	return upper_bound(vec[k].begin(),vec[k].end(),r)
	-lower_bound(vec[k].begin(),vec[k].end(),l);
} // Number of occurrences
void proc(int k,int l,int r,int &ans,int &cnt)
{
	int res=find(k,l,r);
	if(res>cnt||res==cnt&&k<ans)
	{
		cnt=res;
		ans=k;
	} // Update answer
}
void init()
{
	sort(b+1,b+1+n);
	m=unique(b+1,b+1+n)-b-1;
	for(int i=1; i<=n; i++)
	{
		a[i]=lower_bound(b+1,b+1+m,a[i])-b;
		vec[a[i]].push_back(i); // Record subscript
	}
	t=sqrt(log(n)/log(2)*n);
	len=t?n/t:n;
	for(int i=1; i<=t; i++)
	{
		L[i]=(i-1)*len+1;
		R[i]=i*len;
	}
	if(R[t]<n)
	{
		L[t+1]=R[t]+1;
		R[++t]=n;
	}
	for(int i=1; i<=t; i++)
		for(int j=L[i]; j<=R[i]; j++)
			id[j]=i;
	for(int i=1; i<=t; i++)
	{
		memset(c,0,sizeof(c)); // Statistical times
		int cnt=0,ans=0;
		for(int j=L[i]; j<=n; j++)
		{
			++c[a[j]];
			if(c[a[j]]>cnt||c[a[j]]==cnt&&a[j]<ans)
			{
				cnt=c[a[j]];
				ans=a[j];
			}
			f[i][id[j]]=ans; // Mode
		}
	}
}
void solve(int l,int r)
{
	l=(l+last-1)%n+1;
	r=(r+last-1)%n+1;
	if(l>r)swap(l,r);
	int p=id[l],q=id[r],x=0,y=0,ans=0,cnt=0;
	if(p+1<=q-1)x=p+1,y=q-1;
	if(p==q)
	{
		for(int i=l; i<=r; i++)
			proc(a[i],l,r,ans,cnt);
	}else
	{
		for(int i=l; i<=R[p]; i++)proc(a[i],l,r,ans,cnt);
		for(int i=L[q]; i<=r; i++)proc(a[i],l,r,ans,cnt);
	}
	if(f[x][y])proc(f[x][y],l,r,ans,cnt);
	write(last=b[ans]);pc('\n');
}
signed main()
{
	read(n);read(Q);
	for(int i=1; i<=n; i++)
		read(a[i]),b[i]=a[i];
	init();
	while(Q--)
	{
		int l,r;
		read(l);read(r);
		solve(l,r);
	}
	return 0;
}

And then we thought

If you only need to know the number of modes, is there any good way?

[Ynoi2019 simulation] Yuno loves sqrt technology III

Title Link: [Ynoi2019 simulation] Yuno loves sqrt technology III

Question meaning: interval mode occurrence times, forced Online

Similar to solution 2 of the previous problem, this problem t = n t=\sqrt{n} t=n Just

The difference is that we need to preprocess the number of mode occurrences of consecutive blocks

Then, a vector is built for each value to count the subscripts

Then record the subscript of each stored subscript in the vector a x i ax_i axi​

Obviously, the area of nonviolent inquiry, the answer r e s = f [ x ] [ y ] res=f[x][y] res=f[x][y]

Because the number of boundaries is the most, it has a great influence on the answer 2 n 2\sqrt{n} 2n Contribution of

So when querying, for each left element k k k. We just need to find k k In the vector of k a x k + r e s ax_k+res The element at the position of axk + res , to see if it is less than r r r. If less than r r r. It means that it must be closer to the final answer and within this interval, update r e s res res

For each right element k k k. We just need to find k k In the vector of k a x k − r e s ax_k-res The element of the position of axk − res to see if it is greater than l l l. The principle is the same as above

The final answer is r e s res res

Time complexity O ( ( n + m ) n ) O((n+m)\sqrt{n}) O((n+m)n ​)

Spatial complexity O ( n ) O(n) O(n)

The code is as follows

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define MAXN (int)(5e5+5)
#define MAXM (int)(888)
#define pc(a) putchar(a)
template<typename T>inline void read(T &k)
{
	char ch=getchar();T x=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	k=x*f;
}
template<typename T>void write(T k)
{
	if(k<0){pc('-');k=-k;}
	if(k>9)write(k/10);
	pc(k%10+'0');
}
int n,m,Q,last,t,len,c[MAXN],id[MAXN],cnt[MAXN];
int a[MAXN],b[MAXN],L[MAXM],R[MAXM],f[MAXM][MAXM],ax[MAXN];
vector<int> vec[MAXN];
void init()
{
	sort(b+1,b+1+n);
	m=unique(b+1,b+1+n)-b-1;
	for(int i=1; i<=n; i++)
	{
		a[i]=lower_bound(b+1,b+1+m,a[i])-b; // Discretization
		vec[a[i]].push_back(i); // subscript
		ax[i]=vec[a[i]].size()-1; // The subscript of each subscript in the vector
	}
	t=sqrt(n);
	len=t?n/t:n;
	for(int i=1; i<=t; i++)
	{
		L[i]=(i-1)*len+1;
		R[i]=i*len;
	}
	if(R[t]<n)
	{
		L[t+1]=R[t]+1;
		R[++t]=n;
	}
	for(int i=1; i<=t; i++)
		for(int j=L[i]; j<=R[i]; j++)
			id[j]=i;
	for(int i=1; i<=t; i++)
	{
		memset(c,0,sizeof(c));
		for(int j=i; j<=t; j++)
		{
			f[i][j]=f[i][j-1];
			for(int k=L[j]; k<=R[j]; k++)
				f[i][j]=max(++c[a[k]],f[i][j]); 
				// Count the number of times (it doesn't know who the mode is qwq)
		}
	}
}
void solve(int l,int r)
{
	l^=last;r^=last; // Title Requirements
	if(l>r)swap(l,r);
	int p=id[l],q=id[r],x=0,y=0,res=0;
	if(p+1<=q-1)x=p+1,y=q-1;
	if(p==q)
	{
		for(int i=l; i<=r; i++)
			cnt[a[i]]=0;
		for(int i=l; i<=r; i++)
			res=max(++cnt[a[i]],res);
	}else
	{
		res=f[x][y];
		for(int i=l; i<=R[p]; i++)
		{
			int it=ax[i]+res;
			while(it<vec[a[i]].size()&&vec[a[i]][it]<=r)
				{++res;++it;} // Violence expansion + update answer
		}

		for(int i=L[q]; i<=r; i++)
		{
			int it=ax[i]-res;
			while(it>=0&&vec[a[i]][it]>=l)
				{++res;--it;}
		}
	}
	write(last=res);pc('\n');
}
signed main()
{
	read(n);read(Q);
	for(int i=1; i<=n; i++)
		read(a[i]),b[i]=a[i];
	init();
	while(Q--)
	{
		int l,r;
		read(l);read(r);
		solve(l,r);
	}
	return 0;
}

summary

This paper briefly discusses the block solution of lower interval mode

Reprint, please indicate the source

Tags: Algorithm data structure OI

Posted on Fri, 17 Sep 2021 16:49:55 -0400 by robb73