caioj 2061& CH 0x40数据结构进阶(0x44 分块)例题2:蒲公英

二话不说,直接看代码.(说不清楚)

方法1:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define g getchar()
using namespace std;
const int N=40010,T=37;
int a[N],b[N],L[T],R[T],pos[N],c[T][T][N],f[T][T][2],now[2];

void add(int x,int y,int num)
{
	c[x][y][num]++;
	if(c[x][y][num]>now[0]||(c[x][y][num]==now[0]&&num<now[1]))
		now[0]=c[x][y][num],now[1]=num;
}

int ask(int l,int r)
{
	int p=pos[l],q=pos[r];
	int x=0,y=0;
	if(p+1<=q-1)
		x=p+1,y=q-1;
	memcpy(now,f[x][y],sizeof(now));
	if(!x)
	{
		for(int i=l;i<=r;i++)add(x,y,a[i]);
		for(int i=l;i<=r;i++)c[x][y][a[i]]--;//还原 
	}
	else
	{
		for(int i=l;i<=R[p];i++)add(x,y,a[i]);
		for(int i=L[q];i<=r;i++)add(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]]--;
	}
	return b[now[1]];
}

void qr(int &x)
{
	char c=g;bool v=(x=0);
	while(!( ('0'<=c&&c<='9') || c=='-' ))c=g;
	if(c=='-')v=1,c=g;
	while('0'<=c&&c<='9')x=x*10+c-'0',c=g;
	if(v)x=-x;
}
void write(int x)
{
	if(x/10)write(x/10);
	putchar(x%10+'0');
}
int main()
{
	freopen("2061.in","r",stdin);
	freopen("2061.out","w",stdout); 
	int n,m;qr(n);qr(m);
	for(int i=1;i<=n;i++)qr(a[i]),b[i]=a[i];
	//离散化
	sort(b+1,b+n+1);
	int tot=unique(b+1,b+n+1)-(b+1);
	for(int i=1;i<=n;i++)
		a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
	//分块
	int t=pow(1.0*n,1.0/3);//块数 
	int len=t?n/t:n;
	for(int i=1;i<=t;i++) 
		L[i]=R[i-1]+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++)
			pos[j]=i;
	//预处理大块
	for(int i=1;i<=t;i++)
		for(int j=i;j<=t;j++)
		{
			memcpy(c[i][j],c[i][j-1],sizeof(c[i][j]));//c[i][j][k]表示第i块~第j块 k出现的次数
			memcpy(f[i][j],f[i][j-1],sizeof(f[i][j]));//f[i][j][0]表示第i块~第j块众数的出现个数,f[i][j][1]表示那个众数
			for(int k=L[j];k<=R[j];k++)
			{
				++c[i][j][a[k]];
				if(c[i][j][a[k]]>f[i][j][0]||(c[i][j][a[k]]==f[i][j][0]&&a[k]<f[i][j][1]))
					f[i][j][0]=c[i][j][a[k]],f[i][j][1]=a[k];
			}
		}
	int x=0;
	while(m--)
	{
		int l,r;qr(l);qr(r);
		l=(l+x-1)%n+1;
		r=(r+x-1)%n+1;
		if(l>r)swap(l,r);
		x=ask(l,r);
		write(x);puts("");
	}
	return 0;
}

方法2:

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define g getchar()
using namespace std;
const int N=40010,T=788;
int a[N],b[N],c[N],L[N],R[N],pos[N],f[T][T],ans,cnt;
vector<int>s[N];
bool v[N];

void work(int x,int l,int r)
{
	int w=upper_bound(s[x].begin(),s[x].end(),r)-lower_bound(s[x].begin(),s[x].end(),l);
	//等价于lower_bound(s[x].begin(),s[x].end(),r+1)-lower_bound(s[x].begin(),s[x].end(),l);
	if(w>cnt||(w==cnt&&x<ans))
		cnt=w,ans=x;
}

int ask(int l,int r)
{
	ans=cnt=0;
	memset(v,0,sizeof(v));
	int p=pos[l],q=pos[r];
	int x=0,y=0;
	if(p+1<=q-1)
		x=p+1,y=q-1;
	if(!x)
	{
		for(int i=l;i<=r;i++)if(!v[a[i]])
			v[a[i]]=1,work(a[i],l,r);
		return b[ans];
	}
	for(int i=l;i<=R[p];i++)if(!v[a[i]])
		v[a[i]]=1,work(a[i],l,r);
	for(int i=L[q];i<=r;i++)if(!v[a[i]])
		v[a[i]]=1,work(a[i],l,r);
	if(!v[f[x][y]])
		work(f[x][y],l,r);
	return b[ans];
}

void qr(int &x)
{
	char c=g;bool v=(x=0);
	while(!( ('0'<=c&&c<='9') || c=='-' ))c=g;
	if(c=='-')v=1,c=g;
	while('0'<=c&&c<='9')x=x*10+c-'0',c=g;
	if(v)x=-x;
}
void write(int x)
{
	if(x/10)write(x/10);
	putchar(x%10+'0');
}

int main()
{
	freopen("2061.in","r",stdin);
	freopen("2061.out","w",stdout);
	int n,m;qr(n);qr(m);
	for(int i=1;i<=n;i++)qr(a[i]);
	memcpy(b,a,sizeof(b));
	sort(b+1,b+n+1);
	int tot=unique(b+1,b+n+1)-(b+1);
	for(int i=1;i<=n;i++)
	{
		a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
		s[a[i]].push_back(i);
	}
	int t=sqrt(log(1.0*n)/log(2.0)*n);
	int len=t?n/t:n;
	for(int i=1;i<=t;i++)
		L[i]=R[i-1]+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++)
			pos[j]=i;
	memset(f,0,sizeof(f));
	for(int i=1;i<=t;i++)
	{
		memset(c,0,sizeof(c));
		ans=cnt=0;
		for(int j=L[i];j<=n;j++)
		{
			if(++c[a[j]]>cnt||(c[a[j]]==cnt&&a[j]<ans))
				cnt=c[a[j]],ans=a[j];
			f[i][pos[j]]=ans;
		}
	}
	int x=0;
	while(m--)
	{
		int l,r;qr(l);qr(r);
		l=(l+x-1)%n+1;
		r=(r+x-1)%n+1;
		if(l>r)swap(l,r);
		x=ask(l,r);
		write(x);puts("");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/zsyzlzy/p/12373900.html