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

    题目链接

    BZOJ.

    洛谷.

    Solution

    神仙分块。

    首先分成(sqrt{n})大小的块,先预处理(sum[i][v])表示值为(v)的在前(i)个块出现了多少次,离散化之后这部分(O(nsqrt{n}))

    然后预处理(f[i][j])表示第(i)到第(j)个块的众数和出现次数,这个处理可以仿照区间(dp),假设我们处理好了(f[i][j-1]),那么考虑最后一个块的贡献,众数只有可能是前面块的众数或者是后面多出来的数。

    那么可以开个桶(s[i])表示值为(i)的出现了多少次,那么先用前面处理出来的前缀和把前(isim j-1)的块统计好,然后枚举第(j)个块的所有值,更新(s[i])顺便处理答案。

    那么询问也同样的处理,询问可以分成三块,中间的整块和两边的零碎块,整块直接前缀和加预处理出来的(f)更新,零碎的枚举所有值。

    总复杂度(O(nsqrt{n}))

    #include<bits/stdc++.h>
    using namespace std;
    
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    #define lf double
    #define ll long long 
    
    const int maxn = 4e4+10;
    const int inf = 1e9;
    const lf eps = 1e-8;
    
    int f[202][202],h[202][202],g[202][maxn],n,m,v[maxn],R[maxn],s[maxn],st[maxn],ed[maxn],bel[maxn];
    
    int solve(int l,int r) {
    	if(bel[l]==bel[r]) {
    		int res=0,num=0;
    		for(int i=l;i<=r;i++) s[v[i]]=0;
    		for(int i=l;i<=r;i++) {
    			s[v[i]]++;
    			if(s[v[i]]>num||(s[v[i]]==num&&v[i]<res)) num=s[v[i]],res=v[i];
    		}return res;
    	}
    	int res=f[bel[l]+1][bel[r]-1],num=h[bel[l]+1][bel[r]-1];
    	for(int i=l;i<=ed[bel[l]];i++) s[v[i]]=0;
    	for(int i=st[bel[r]];i<=r;i++) s[v[i]]=0;
        
    	for(int i=l;i<=ed[bel[l]];i++)
    		if(!s[v[i]]) s[v[i]]=g[bel[r]-1][v[i]]-g[bel[l]][v[i]];
    	for(int i=st[bel[r]];i<=r;i++)
    		if(!s[v[i]]) s[v[i]]=g[bel[r]-1][v[i]]-g[bel[l]][v[i]];
    	
    	for(int i=l;i<=ed[bel[l]];i++) {
    		s[v[i]]++;
    		if(s[v[i]]>num||(s[v[i]]==num&&v[i]<res)) num=s[v[i]],res=v[i];
    	}
    	for(int i=st[bel[r]];i<=r;i++) {
    		s[v[i]]++;
    		if(s[v[i]]>num||(s[v[i]]==num&&v[i]<res)) num=s[v[i]],res=v[i];
    	}return res;
    }
    
    int main() {
    	read(n),read(m);int b=ceil(sqrt(n));
    	for(int i=1;i<=n;i++) read(v[i]),R[i]=v[i];
    	sort(R+1,R+n+1);int M=unique(R+1,R+n+1)-R-1;
    	for(int i=1;i<=n;i++) v[i]=lower_bound(R+1,R+M+1,v[i])-R;
    	
    	for(int i=1;i<=n;i++) bel[i]=(i-1)/b+1;int cnt=bel[n];
    	for(int i=1;i<=n;i++) st[bel[i]]=bel[i]==bel[i-1]?st[bel[i-1]]:i;
    	for(int i=n;i;i--) ed[bel[i]]=bel[i]==bel[i+1]?ed[bel[i+1]]:i;
    	
    	for(int i=1;i<=n;i++)
    		for(int j=bel[i];j<=cnt;j++) g[j][v[i]]++;
    	
    	for(int x=1;x<=cnt;x++) {
    		int res=0,num=0;
    		for(int i=st[x];i<=ed[x];i++) s[v[i]]=0;
    		for(int i=st[x];i<=ed[x];i++) {
    			s[v[i]]++;
    			if(s[v[i]]>num||(s[v[i]]==num&&v[i]<res)) res=v[i],num=s[v[i]];
    		}f[x][x]=res,h[x][x]=num;
    	}
    		
    	for(int len=2;len<=cnt;len++) 
    		for(int j=1;j<=cnt-len+1;j++) {
    			int l=j,r=j+len-1;f[l][r]=f[l][r-1],h[l][r]=h[l][r-1];
    			for(int i=st[r];i<=ed[r];i++) s[v[i]]=0;
    			for(int i=st[r];i<=ed[r];i++)
    				if(!s[v[i]]) s[v[i]]=g[r-1][v[i]]-g[l-1][v[i]];
    			for(int i=st[r];i<=ed[r];i++) {
    				s[v[i]]++;
    				if(s[v[i]]>h[l][r]||(s[v[i]]==h[l][r]&&v[i]<f[l][r])) f[l][r]=v[i],h[l][r]=s[v[i]];
    			}
    		}
    	
    	int lstans=0;
    	for(int i=1,l,r;i<=m;i++) {
    		read(l),read(r);
    		l=(l+lstans-1)%n+1,r=(r+lstans-1)%n+1;
    		if(l>r) swap(l,r);
    		write(lstans=R[solve(l,r)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    linux中文字体
    连接数据库服务器端的几个常见错误
    分布式部署下的报表调用 API调用 权限问题以及性能方案
    报表在IBM AIX系统下resin部署
    ASP.Net与JSP如何共享Session值
    async与await
    从小程序到小程序云开发
    什么是 FOUC(无样式内容闪烁)?你如何来避免 FOUC?
    微信小程序知识云开发
    变量的解构赋值
  • 原文地址:https://www.cnblogs.com/hbyer/p/10620243.html
Copyright © 2011-2022 走看看