• 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;
    }
    

      

  • 相关阅读:
    .gitignore 文件没起作用
    HTML 中img标签不显示
    关于拖拽
    关于javascript三目
    封装ajax
    javascript-时间戳
    关于Vue实例的生命周期created和mounted的区别
    ES6核心内容讲解
    jsonp跨域请求
    javascript-AJAX
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html
Copyright © 2020-2023  润新知