zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    学习ActiveMQ(五):activemq的五种消息类型和三种监听器类型
    学习ActiveMQ(三):发布/订阅模式(topic)演示
    学习ActiveMQ(二):点对点(队列)模式消息演示
    Linux系统基础优化及常用命令
    【原创】Access自动编号的初始值设置及重置编号
    【整理】引用类型与ref传递实例精解
    【原创】数据库操作类库整理
    【摘录】Random快速产生相同随机数的原因及解决方案
    【整理】辗转相除法求最大公约数算法证明
    【转载】access采用sql语句与msql的区别
  • 原文地址:https://www.cnblogs.com/zsyzlzy/p/12373900.html
Copyright © 2011-2022 走看看