【Ynoi2019】Yuno loves sqrt technology III

【Ynoi2019】Yuno loves sqrt technology III

by AmanoKumiko

Description

给出长为n的序列am次询问一个区间众数的出现次数

强制在线

Input

第一行两个数n,m

然后一行n个数读入a

然后m行每行两个数l,r读入询问

Output

输出m

每行一个数表示答案

Sample Input

4 1
2 3 3 3
2 4

Sample Output

3

Data Constraint

1n,m5105,0ai109

Solution

一道喵喵题

首先我们转化一下

变成询问区间最大出现次数

可以想到一个序列分块做法

我们设Maxi,j表示第i到第j块的最大出现次数

然后记Si,j表示前i块,数j的出现次数

两者都可以O(nn)预处理

查询时暴力加入,也是O(nn)

但是有一个问题

这题的空间只够线性

你考虑这样一件事,就是说

对于当前的答案ans,枚举散块加入时,每次的增量都是O(1)

那么假设当前这个数是这种数的第i个,只需第i+ans个也在这个区间内就行了

记录下每个数的排名,然后vector保存每种数

于是我们成功解决了这道题

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define N 500010
#define M 800

unordered_map<int,int>v;
vector<int>pos[N];
int n,B,sz,m,a[N],L[N],R[N],be[N],Max[M][M],tmp[N],cnt,id[N],ans,num[N];

int main(){
	scanf("%d%d",&n,&m);
	B=sqrt(n)+1;sz=n/B+1;
	F(i,1,sz){
		L[i]=R[i-1]+1;R[i]=min(n,L[i]+B-1);
		F(j,L[i],R[i])be[j]=i;
	}
	F(i,1,n){
		scanf("%d",&a[i]);
		if(v.find(a[i])==v.end())v[a[i]]=++cnt;
		id[i]=v[a[i]];
		pos[id[i]].push_back(i);
		num[i]=pos[id[i]].size();
	}
	F(i,1,sz){
		F(j,i,sz){
			Max[i][j]=Max[i][j-1];
			F(k,L[j],R[j]){
				tmp[id[k]]++;
				Max[i][j]=max(Max[i][j],tmp[id[k]]);
			}
		}
		memset(tmp,0,sizeof(tmp));
	}
	F(i,1,m){
		int l,r;
		scanf("%d%d",&l,&r);
		l^=ans;r^=ans;
		if(be[l]==be[r]){
			ans=0;
			F(j,l,r)tmp[id[j]]++,ans=max(ans,tmp[id[j]]);
			F(j,l,r)tmp[id[j]]=0;
			printf("%d\n",ans);
		}else{
			ans=max(0,Max[be[l]+1][be[r]-1]);
			Fd(j,R[be[l]],l)if(num[j]+ans<=pos[id[j]].size()){
				if(l<=pos[id[j]][num[j]+ans-1]&&pos[id[j]][num[j]+ans-1]<=r)ans++;
			}
			F(j,L[be[r]],r)if(num[j]-ans-1>=0){
				if(l<=pos[id[j]][num[j]-ans-1]&&pos[id[j]][num[j]-ans-1]<=r)ans++;
			}
			printf("%d\n",ans);
		}
	}
	return 0;
}
posted @   冰雾  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示