题目链接:https://loj.ac/problem/6285
题目描述
给出一个长为 n 的数列,以及 n 个操作,操作涉及询问区间的最小众数。
输入格式
第一行输入一个数字 n。
第二行输入 n 个数字,第 i个数字为 ai,以空格隔开。
接下来输入 n 行询问,每行输入两个数字 l、r,以空格隔开。
表示查询位于 [l,r] 的数字的众数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 4
1 2
1 4
2 4
3 4
样例输出
1
2
2
2
思路:分块的思维,先将n分块,预处理每两块之间的众数,在用二分求不完整块中每个数是否可能为众数。
这里用id转换数值,将值变成第几个出现的数。
代码:
#include<iostream> #include<algorithm> #include<vector> #include<map> #include<cstdio> #include<cstring> #include<cmath> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=1e5+10; int a[maxn],MAX[2020][2020],id,n,block; int pos[maxn],val[maxn],num[maxn];//pos记录在哪个块,val[i]记录编号为i的原值,num用来求众数 map<int,int >mp; vector<int>v[maxn];//储存编号相同,即数相同时的原来的第几个值。用来二分求众数用 bool visit[maxn];//标记 void init(int x)//预处理每块之间的众数 { int count=0,max1=0; memset(num,0,sizeof(num)); for(int i=(x-1)*block+1;i<=n;i++) { num[a[i]]++; if(num[a[i]]>count||num[a[i]]==count&&val[a[i]]<val[max1])//找最小众数 { count=num[a[i]]; max1=a[i]; } MAX[x][pos[i]]=max1; } } int er(int x,int l,int r)//二分查找块内,编号为x的数量 { return upper_bound(v[x].begin(),v[x].end(),r)-lower_bound(v[x].begin(),v[x].end(),l); } int solve(int l,int r) { int ans=MAX[pos[l]+1][pos[r]-1],count=0;//中间一整块的众数 memset(visit,0,sizeof(visit)); count=er(ans,l,r); visit[ans]=1; for(int i=l;i<=min(pos[l]*block,r);i++)//暴力左边不完整块中每个数是否可能为众数 { if(visit[a[i]]==0) { visit[a[i]]=1; int count1=er(a[i],l,r); if(count1>count||count1==count&&val[a[i]]<val[ans]) { count=count1; ans=a[i]; } } } if(pos[l]!=pos[r])//暴力右边不完整块中每个数是否可能为众数 { for(int i=(pos[r]-1)*block+1;i<=r;i++) { if(visit[a[i]]==0) { visit[a[i]]=1; int count1=er(a[i],l,r); if(count1>count||count1==count&&val[a[i]]<val[ans]) { count=count1; ans=a[i]; } } } } return val[ans]; } int main() { scanf("%d",&n); block=80; id=0; for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pos[i]=(i-1)/block+1; if(mp[a[i]]==0) { mp[a[i]]=++id;//id第几个出现的数 val[id]=a[i];//保存原始值 } a[i]=mp[a[i]];//保存编号(第几个出现的数) v[a[i]].push_back(i); } for(int i=1;i<=pos[n];i++) init(i); int l,r; for(int i=1;i<=n;i++) { scanf("%d%d",&l,&r); printf("%d\n",solve(l,r)); } return 0; }