• BZOJ 2724--蒲公英(分块)


    2724: [Violet 6]蒲公英

    Time Limit: 40 Sec  Memory Limit: 512 MB
    Submit: 2507  Solved: 869
    [Submit][Status][Discuss]

    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

    题目链接:

        http://www.lydsy.com/JudgeOnline/problem.php?id=2724 

    Solution

        经典的分块,众数是不可合并的,所以不能用线段树来维护。。。

        这时候就要用分块啦。。。。

        一个定理:两个集合的众数一定包含于一个集合和另一个集合的众数中。

        然后预处理出第 i 块 到 第 j 块的众数,还有位置 i 到 j 的某种元素的个数。。

        之后用分块维护就好了。。。

    代码

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<iostream>
    #include<queue>
    #include<vector>
    #include<map>
    #define N 40050
    #define LL long long
    using namespace std;
    inline int Read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,Q,e,m,cnt=0,x=0,t=0;
    int a[N],b[N],g[N],sum[N],f[250][250],vis[N];
    map<int,int>mp;
    vector<int> q[N];
    void reset(int k){
    	int mx=0,s=0;
    	for(int i=1;i<=cnt;i++) sum[i]=0;
    	for(int i=(k-1)*e+1;i<=n;i++) {
    		sum[a[i]]++;
    		if(sum[a[i]]>sum[mx] || (sum[a[i]]==sum[mx]&&b[a[i]]<b[mx])) mx=a[i];
    		f[k][g[i]]=mx;
    	}
    }
    int calc(int h,int c){
    	int l=0,r=q[c].size()-1,mid;
    	if(q[c][l]>h) return 0;if(q[c][r]<=h) return q[c].size();
    	while(l!=r){
    		mid=(l+r+1)>>1;
    		if(q[c][mid]<=h) l=mid;
    		else r=mid-1;
    	}
    	return l+1;
    }
    void solve(int l,int r,int K){
    	int now;
    	x=0;t=0;
    	if(g[l]==g[r]){
    		for(int i=l;i<=r;i++){
    			if(vis[a[i]]==K) continue;vis[a[i]]=K;
    			now=calc(r,a[i])-calc(l-1,a[i]);
    			if(now>t || (now==t && b[a[i]]<b[x])){x=a[i];t=now;}
    		}
    		x=b[x];
    		printf("%d
    ",x);
    		return;
    	}
    	for(int i=l;i<=e*(g[l]);i++) {
    		if(vis[a[i]]==K) continue;vis[a[i]]=K;
    		now=calc(r,a[i])-calc(l-1,a[i]);
    		if(now>t || (now==t && b[a[i]]<b[x])){x=a[i];t=now;}
    	}
    	for(int i=(g[r]-1)*e+1;i<=r;i++) {
    		if(vis[a[i]]==K) continue;vis[a[i]]=K;
    		now=calc(r,a[i])-calc(l-1,a[i]);
    		if(now>t || (now==t && b[a[i]]<b[x])){x=a[i];t=now;}
    	}
    	if(g[r]-1>=g[l]+1) {
    		int j=f[g[l]+1][g[r]-1];
    		now=calc(r,j)-calc(l-1,j);
    		if(now>t || (now==t && b[j]<b[x])){x=j;t=now;}
    	}
    	x=b[x];
    	printf("%d
    ",x);
    	return;
    }
    int main(){
    	char ch;
    	LL l,r;
    	n=Read();Q=Read();e=ceil(sqrt(n));
    	for(int i=1;i<=n;i++) {
    		a[i]=Read();
    		if(!mp[a[i]]){
    			mp[a[i]]=++cnt;
    			b[cnt]=a[i];
    		}
    		a[i]=mp[a[i]];
    		q[a[i]].push_back(i);
    		g[i]=(i+e-1)/e;
    	}
    	m=g[n];
    	for(int i=1;i<=m;i++) reset(i);
    	for(int i=1;i<=Q;i++){
    		l=(Read()+x-1)%n+1;r=(Read()+x-1)%n+1;
    		if(l>r) swap(l,r);
    		solve(l,r,i);
    	}
    	return 0;
    }
    

      

      

    This passage is made by Iscream-2001.

  • 相关阅读:
    golang json字符串合并操作
    goland 无法跳转 struct等
    golang 中mgo update报错: The dollar ($) prefixed field '$inc' in '$inc' is not valid for storage.
    解决windows下使用vscode没有函数提示的问题
    【转载,实测好用】gitlab结合sourcetree使用
    C++单继承、多继承情况下的虚函数表分析
    Linux 日志文件管理——限制大小
    C++ RCSP智能指针简单实现与应用
    Makefile模板(C++)
    Git关于pull,commit,push的总结
  • 原文地址:https://www.cnblogs.com/Yuigahama/p/8080339.html
Copyright © 2020-2023  润新知