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

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html

    题目传送门 - BZOJ2724

    题意

      求区间最小众数,强制在线。

      $n$ 个数,$m$ 次询问。

      $nleq 40000,mleq 50000$

    题解

      看完题目:呀这不是莫队裸题吗??

      再看一遍:我去怎么是强制在线!

      然后经过一波思(forever)考(piano),终于会做了。

      首先请你自行证明一个结论:

    在询问区间内任取一段子区间,询问区间内的最小众数一定是子区间的最小众数或者出现在询问区间除掉子区间的其他地方。

      于是我们考虑分块,$base=sqrt{maxn}=200$ 一块。

      我们考虑对于所有 $i,j$ 预处理出第 $i$ 块到第 $j$ 块的区间最小众数。

      我还要预处理出每一个数在前 $i$ 块的出现次数 $left(iin left[1,leftlfloorcfrac{n}{base} ight floor ight] ight)$ 。

      于是在询问的时候只要看一看询问区间最大连续块段的最小众数和其他剩余的数就可以了。

      时间复杂度 $Theta (n sqrt{n})$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=40005,M=205,base=200;
    int n,m,hs,a[N],Ha[N],res[M][M],cnt[M][N],tax[N];
    int l,r,L,R;
    void HASH(){
    	sort(Ha+1,Ha+n+1);
    	hs=1;
    	for (int i=2;i<=n;i++)
    		if (Ha[i]!=Ha[i-1])
    			Ha[++hs]=Ha[i];
    }
    int calc(int x){
    	return tax[x]+cnt[r][x]-cnt[l][x];
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%d",&a[i]),Ha[i]=a[i];
    	HASH();
    	for (int i=1;i<=n;i++)
    		a[i]=lower_bound(Ha+1,Ha+hs+1,a[i])-Ha;
    	memset(cnt,0,sizeof cnt);
    	for (int i=1;i<=base&&i*base<=n;i++)
    		for (int j=1;j<=i*base;j++)
    			cnt[i][a[j]]++;
    	for (int i=1;i<=base&&i*base<=n;i++){
    		memset(tax,0,sizeof tax);
    		for (int j=i;j<=base&&j*base<=n;j++){
    			int &Max=res[i][j];
    			Max=res[i][j-1];
    			for (int k=(j-1)*base+1,lim=j*base;k<=lim;k++){
    				tax[a[k]]++;
    				if (tax[a[k]]>tax[Max]||(tax[a[k]]==tax[Max]&&a[k]<Max))
    					Max=a[k];
    			}
    		}
    	}
    	memset(tax,0,sizeof tax);
    	int ans=0;
    	while (m--){
    		scanf("%d%d",&L,&R);
    		L=(L+Ha[ans]-1)%n+1,R=(R+Ha[ans]-1)%n+1;
    		if (L>R)
    			swap(L,R);
    		ans=0;
    		if (R-L+1<=base*2){
    			for (int i=L;i<=R;i++)
    				tax[a[i]]++;
    			for (int i=L;i<=R;i++)
    				if (tax[a[i]]>tax[ans]||(tax[a[i]]==tax[ans]&&a[i]<ans))ans=a[i];
    			for (int i=L;i<=R;i++)
    				tax[a[i]]--;
    			printf("%d
    ",Ha[ans]);
    			continue;
    		}
    		l=(L-1)/base+1,r=R/base;
    		ans=res[l+1][r];
    		for (int i=L;i<=l*base;i++)
    			tax[a[i]]++;
    		for (int i=r*base+1;i<=R;i++)
    			tax[a[i]]++;
    		for (int i=L;i<=l*base;i++)
    			if (calc(a[i])>calc(ans)||(calc(a[i])==calc(ans)&&a[i]<ans))ans=a[i];
    		for (int i=r*base+1;i<=R;i++)
    			if (calc(a[i])>calc(ans)||(calc(a[i])==calc(ans)&&a[i]<ans))ans=a[i];
    		for (int i=L;i<=l*base;i++)
    			tax[a[i]]--;
    		for (int i=r*base+1;i<=R;i++)
    			tax[a[i]]--;
    		printf("%d
    ",Ha[ans]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    (转)MySQL中MyISAM引擎与InnoDB引擎性能简单测试
    (转)数据库水平切分的实现原理解析
    ECShop笔记(品牌类)
    ECShop笔记(通用类)
    (转)InnoDB的性能(zz)
    ECSHOP笔记(商品类 三)
    ECShop笔记(积分类)
    ECShop笔记(商品类)
    ECShop笔记(二)
    phpcms 点击排行榜的改进
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html
Copyright © 2011-2022 走看看