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\n",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\n",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.

 

posted @ 2017-12-21 14:25  Iscream-2001  阅读(178)  评论(0编辑  收藏  举报
/* */ /* */