#include<iostream>
#include<algorithm>
#include<map>
#include<vector>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<cstdlib>
#define ll long long
#define inf 0x3f3f3f3f
#define N 1000009
using namespace std;
map<int,int>mp;//离散化
vector<int> vec[N];//记录每个值出现的位置
int blo[N],v[N],val[N],cnt[N];
int f[505][505];//记录(i,j)的众数
int id,len,n;
ll read()
{
char ch=getchar();ll f=1,ret=0;
while(ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
return f*ret;
}
void pre(int x)//预处理从x~i(i=x~n)的众数
{
int mx=0,cur=0;
memset(cnt,0,sizeof(cnt));
for (int i=(x-1)*len+1;i<=n;i++)
{
int pos=blo[i];
cnt[v[i]]++;
if (cnt[v[i]]>mx||(cnt[v[i]]==mx&&val[v[i]]<val[cur]))//如果v[i]出现的次数多,或者次数一样多但值小
cur=v[i],mx=cnt[v[i]];
f[x][pos]=cur;//在(x,blo[i])的块间众数更新
}
}
int ask(int l,int r,int x)//询问在区间(l,r)之间,数值为x的数出现的次数
{return (upper_bound(vec[x].begin(),vec[x].end(),r)-lower_bound(vec[x].begin(),vec[x].end(),l));}
int query(int l,int r)
{
int p=blo[l],q=blo[r],ans=f[p+1][q-1],mx=0;
mx=ask(l,r,ans);//先找在块(blo[l]+1,blo[r]-1)的众数在区间(l,r)之间出现的次数
for (int i=l;i<=min(p*len,r);i++)//然后我们暴力处理从整块两边多余的部分
{
int t=ask(l,r,v[i]);
if (t>mx||(t==mx&&val[ans]>val[v[i]])) mx=t,ans=v[i];
}
if (p!=q)
for (int i=(q-1)*len+1;i<=r;i++)
{
int t=ask(l,r,v[i]);
if (t>mx||(t==mx&&val[ans]>val[v[i]])) mx=t,ans=v[i];
}
return val[ans];
}
int main()
{
n=read();len=200;
for (int i=1;i<=n;i++)
{
v[i]=read();
if (!mp[v[i]])//如果这个值并没有离散化,离散化
{
mp[v[i]]=++id;
val[id]=v[i];
}
v[i]=mp[v[i]];
vec[v[i]].push_back(i);
}
for (int i=1;i<=n;i++) blo[i]=(i-1)/len+1;
for (int i=1;i<=blo[n];i++) pre(i);
for (int i=1;i<=n;i++)
{
int l=read(),r=read();
if (l>r) swap(l,r);
printf("%d\n",query(l,r));
}
return 0;
}
【loj6285】 数列分块入门 9
最新推荐文章于 2021-09-22 23:09:42 发布