zoukankan      html  css  js  c++  java
  • 【BZOJ2724】[Violet 6]蒲公英 分块+二分

    【BZOJ2724】[Violet 6]蒲公英

    Description

    Input

    修正一下

    l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

    Output

    Sample Input

    6 3
    1 2 3 2 1 2
    1 5
    3 6
    1 5

    Sample Output

    1
    2
    1

    HINT

    修正下:

    n <= 40000, m <= 50000

    题解:分块还是练脑子啊~

    结论:一个区间的众数要么是区间中一个块的众数,要么是块外的任意一个数。

    这就告诉我们需要预处理出任意两个块之间的所有数的众数,这个可以用离散化+桶+扫一遍实现。

    那么对于询问[l,r]我们假设其中最大的连续的块是[ll,rr],那么我们已知了[ll,rr]中的众数,如何判断[l,ll),(rr,r]中的数是不是众数呢?

    既然已经将所有数离散化了,我们就可以考虑记录每个数出现的位置。我们将每个数出现的位置从左到右用vector存起来,然后查询的时候二分一下,就知道了这个数在[l,r]中出现了多少次,用它来更新答案就行了。

    sqrt(n/logn)大法好~

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <vector>
    #include <algorithm>
    using namespace std;
    const int maxn=40010;
    int n,m,nm,B,mx,ans;
    int v[maxn],st[maxn],ref[maxn];
    int s[810][810];
    vector<int> pos[maxn];
    struct node
    {
    	int org,val;
    }num[maxn];
    bool cmp(node a,node b)
    {
    	return a.val<b.val;
    }
    int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    void query(int a,int b,int x)
    {
    	if(!x||st[x])	return ;
    	int l=0,r=pos[x].size()-1,mid,c,d;
    	while(l<r)
    	{
    		mid=l+r>>1;
    		if(pos[x][mid]>=a)	r=mid;
    		else	l=mid+1;
    	}
    	c=r;
    	l=0,r=pos[x].size();
    	while(l<r)
    	{
    		mid=l+r>>1;
    		if(pos[x][mid]<=b)	l=mid+1;
    		else	r=mid;
    	}
    	d=l-1,st[x]=d-c+1;
    	if(st[x]>st[mx]||(st[x]==st[mx]&&x<mx))	mx=x;
    }
    int main()
    {
    	//freopen("bz2724.in","r",stdin);
    	n=rd(),m=rd();
    	int i,j,a,b,c,d;
    	for(i=0;i<n;i++)	num[i].val=rd(),num[i].org=i;
    	sort(num,num+n,cmp);
    	for(i=0;i<n;i++)
    	{
    		if(!i||num[i].val>num[i-1].val)	ref[++nm]=num[i].val;
    		v[num[i].org]=nm;
    	}
    	B=int(sqrt(double(n)/log(n)));
    	for(i=0;i<n;i++)	pos[v[i]].push_back(i);
    	for(i=0;i*B<n;i++)
    	{
    		memset(st,0,sizeof(st));
    		for(mx=0,j=i*B;j<n;j++)
    		{
    			st[v[j]]++;
    			if(st[v[j]]>st[mx]||(st[v[j]]==st[mx]&&v[j]<mx))	mx=v[j];
    			s[i][j/B]=mx;
    		}
    	}
    	memset(st,0,sizeof(st));
    	for(i=1;i<=m;i++)
    	{
    		a=(rd()+ans-1+n)%n,b=(rd()+ans-1+n)%n;
    		if(a>b)	swap(a,b);
    		c=a/B,d=b/B;
    		if(c==d)
    		{
    			for(mx=0,j=a;j<=b;j++)
    			{
    				st[v[j]]++;
    				if(st[v[j]]>st[mx]||(st[v[j]]==st[mx]&&v[j]<mx))	mx=v[j];
    			}
    			ans=ref[mx],printf("%d
    ",ans);
    			for(j=a;j<=b;j++)	st[v[j]]--;
    			continue;
    		}
    		mx=0,query(a,b,s[c+1][d-1]);
    		for(j=a;j<c*B+B;j++)	query(a,b,v[j]);
    		for(j=d*B;j<=b;j++)	query(a,b,v[j]);
    		ans=ref[mx],printf("%d
    ",ans);
    		st[s[c+1][d-1]]=0;
    		for(j=a;j<c*B+B;j++)	st[v[j]]=0;
    		for(j=d*B;j<=b;j++)	st[v[j]]=0;
    	}
    	return 0;
    }
  • 相关阅读:
    WordCloud 简介
    Volo.Abp.EntityFrameworkCore.MySQL 使用
    关于Git的那些事
    国内外各大免费搜索引擎、导航网址提交入口
    C#读取Excel的数据,并且以混合模式读取,防止数据类型变更
    如何提升程序员的非技术才能
    用户体验设计流程与文档编制指南
    【海量干货】89页PPT详解微信O2O行业解决方案
    AutoCompleteTextView 和 MultiAutoCompleteTextView 自动完成文本控件
    zookeeper简介
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7071323.html
Copyright © 2011-2022 走看看