zoukankan      html  css  js  c++  java
  • [Luogu P4168] [Violet]蒲公英 (分块)

    题面

    洛咕


    Solution

    题目要求求出区间众数,强制在线。

    区间众数是一个比较尴尬的问题,我们无法用区间数据结构来处理这个问题,因为我们没法很好的合并区间众数的答案。

    既然区间数据结构解决不了这个问题,我们可以考虑一下使用基于分块的算法,例如莫队。
    这题用莫队非常好处理,不幸的是,这题要求强制在线。
    因此我们考虑使用分块算法。

    分块算法的核心在于把一整个块的信息压缩起来以便快速处理。
    我们要查询一段区间的众数,我们可以考虑这样搞:对于这个区间内连续的块,我们先快速地查询这个连续的块中的众数,然后我们暴力处理这个区间剩余的左右两个零散的点,开一个桶暴力维护这些零散的点每个颜色出现的次数,每新加入一个点,就与整个区间的答案比较一下,如果更优就替换答案。

    为了实现上面那个思路,我们必须要实现两点:快速求出一段连续块的每个颜色出现的次数,快速求出一段连续块的众数。
    对于第一个问题,解决方法很简单,我们暴力做前缀和即可,复杂度(O(n*sqrt n))

    for(int i=1;i<=cnt_block;i++)
    	{
    		for(int j=1;j<=to;j++)
    			pre[i][j]=pre[i-1][j];
    		for(int j=(i-1)*size;j<i*size;j++)
    			pre[i][a[j]]++;
    	}
    

    对于第二个问题,我们可以考虑把每段连续块的答案预处理出来。
    具体做法是:我们枚举每个块,然后我们暴力往后扫描,每扫到一个块的结尾就记录答案。

    cnt[0]=-0x3f3f3f3f;
    	for(int i=1;i<=cnt_block;i++)
    	{
    		int t_ans=0;
    		for(int j=(i-1)*size;j<=n;j++)
    		{
    			cnt[a[j]]++;
    			if(cnt[a[j]]>cnt[t_ans] or (cnt[a[j]]==cnt[t_ans] and a[j]<t_ans)) 
    				t_ans=a[j];
    			if((j+1)%size==0)
    				f[i][j/size+1]=t_ans;
    		}
    		memset(cnt,0,sizeof cnt);
    		cnt[0]=-0x3f3f3f3f;
    	}
    

    就酱,这题就被我们搞定啦~
    复杂度(O(nsqrt n))


    Code

    本题实现上有较多细节要处理,请小心

    //Luogu P4168 [Violet]蒲公英
    //Feb,4th,2019
    //分块套路题
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    long long read()
    {
    	long long x=0,f=1; char c=getchar();
    	while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
    	while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    	return x*f;
    }
    const int N=40000+1000;
    const int M=200+10;
    int n,m,a[N],b[N],t_n,mmap[N];//离散值->原值
    int f[M][M],pre[M][N];//f[i][j]:块i到j的众数,pre[i][j]:到i块为止,颜色j的出现次数前缀和
    int cnt[N];//零时记录每个元素出现次数
    int main()
    {
    	//freopen("testdata.in","r",stdin);
    	//freopen("4168.out","w",stdout);
    	
    	t_n=n=read(),m=read();
    	for(int i=1;i<=n;i++)
    		a[i]=read(),b[i]=a[i];
    	
    	sort(b+1,b+1+n);
    	int to=0,last=0;
    	for(int i=1;i<=n;i++)
    		if(b[i]!=last)
    			last=b[i],b[++to]=b[i];
    	for(int i=1;i<=n;i++)
    	{
    		int t=lower_bound(b+1,b+1+to,a[i])-b;
    		mmap[t]=a[i],a[i]=t;
    	}
    	int size=int(sqrt(n)),cnt_block=n/size+1;
    	n=cnt_block*size-1;
    	for(int i=1;i<=cnt_block;i++)
    	{
    		for(int j=1;j<=to;j++)
    			pre[i][j]=pre[i-1][j];
    		for(int j=(i-1)*size;j<i*size;j++)
    			pre[i][a[j]]++;
    	}
    	cnt[0]=-0x3f3f3f3f;
    	for(int i=1;i<=cnt_block;i++)
    	{
    		int t_ans=0;
    		for(int j=(i-1)*size;j<=n;j++)
    		{
    			cnt[a[j]]++;
    			if(cnt[a[j]]>cnt[t_ans] or (cnt[a[j]]==cnt[t_ans] and a[j]<t_ans)) 
    				t_ans=a[j];
    			if((j+1)%size==0)
    				f[i][j/size+1]=t_ans;
    		}
    		memset(cnt,0,sizeof cnt);
    		cnt[0]=-0x3f3f3f3f;
    	}
    	
    	int ans=0;
    	for(int i=1;i<=m;i++)
    	{
    		int l=read(),r=read();
    		l=(l+ans-1)%t_n+1,r=(r+ans-1)%t_n+1;
    		if(l>r) swap(l,r);
    		
    		int bl=l/size+1,br=r/size+1;
    		ans=0;
    		if(bl+1<=br-1)
    			ans=f[bl+1][br-1];
    		for(int j=l;j<bl*size and j<=r;j++)
    		{
    			cnt[a[j]]++;
    			int tmp1=cnt[a[j]],tmp2=cnt[ans];
    			if(bl+1<=br-1)
    				tmp1+=pre[br-1][a[j]]-pre[bl][a[j]],
    				tmp2+=pre[br-1][ans]-pre[bl][ans];
    			if(tmp1>tmp2 or (tmp1==tmp2 and a[j]<ans)) 
    				ans=a[j];
    		}
    		if(bl!=br)
    			for(int j=(br-1)*size;j<=r;j++)
    			{
    				cnt[a[j]]++;
    				int tmp1=cnt[a[j]],tmp2=cnt[ans];
    				if(bl+1<=br-1)
    					tmp1+=pre[br-1][a[j]]-pre[bl][a[j]],
    					tmp2+=pre[br-1][ans]-pre[bl][ans];
    				if(tmp1>tmp2 or (tmp1==tmp2 and a[j]<ans)) 
    					ans=a[j];
    			}
    			
    		for(int j=l;j<bl*size and j<=r;j++)
    			cnt[a[j]]--;
    		if(bl!=br)
    			for(int j=(br-1)*size;j<=r;j++)
    				cnt[a[j]]--;
    		cnt[0]=-0x3f3f3f3f;
    		
    		ans=mmap[ans];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    织梦DedeCms网站首页不生成html文件动态显示方法
    PHP7.0下安装DEDE织梦 出现 GD不支持的解决方法
    DEDECMS5.7支持伪静态的方法
    DEDECMS全站伪静态设置方法
    设置 SSH 通过密钥登录
    Windows安装OpenSSH服务
    VS Code远程开发工具错误-找不到SSH安装
    帝国CMS自定义列表的排序
    帝国CMS灵动标签e:loop的使用方法
    cisco 3750交换机堆叠后配置恢复方法
  • 原文地址:https://www.cnblogs.com/GoldenPotato/p/10351638.html
Copyright © 2011-2022 走看看