0
点赞
收藏
分享

微信扫一扫

LOJ6285.数列分块入门 9(分块在线求区间众数)

Raow1 2022-07-15 阅读 42


​​link​​

思路:

考虑对于查询的区间来说众数出现的几种可能:

  • 左端点所在块的数
  • 右端点所在块的数
  • 的块的众数

对于每一种可能,我们都计算出他出现的次数,最后取出现次数最多并且值最小的就可以。

  • 如何求某个数在某段区间的出现次数呢?大概有两种做法,一是前缀和,二是二分;对于每一个数都用存储一下他出现过的位置,每次用就是答案。
  • 由于的范围过大,所以需要离散化一波~
  • 对于前两种可能,我们可以直接枚举出现的每个数,复杂度为;
  • 第三种可能,直接枚举显然不现实。预处理出表示第块到第块的众数。

for(int i=1;i<=num;i++){
int res=0,cnt=0;
memset(mp,0,sizeof mp);
for(int j=(i-1)*block+1;j<=n;j++){
mp[a[j]]++;
if(mp[a[j]]>cnt) cnt=mp[a[j]],res=a[j];
else if(mp[a[j]]==cnt&&a[j]<res) res=a[j];
dp[i][belong[j]]=res;
}
}

枚举表示起始块的编号,表示后面的数,递推过去就好了。时间复杂度为

  • 对于查询的时候,枚举每一个可能的数并且计算出现的次数,取最大值就好了。
  • 要注意,离散化后的下标关系,容易搞混。

代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll>PLL;
typedef pair<int, int>PII;
typedef pair<double, double>PDD;
#define I_int ll
inline ll read(){ll 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;}

inline void write(ll x){if (x < 0) x = ~x + 1, putchar('-');if (x > 9) write(x / 10);putchar(x % 10 + '0');}

#define read read()
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)

ll ksm(ll a, ll b,ll mod){ll res = 1;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}

const int maxn=100000+7,maxm=2e5+7,inf=0x3f3f3f3f;

int a[maxn],b[maxn],n,block,m,l[5100],r[5100],belong[maxn];
vector<int>g[maxn];
int dp[5100][5100],mp[maxn];
int Find(int x, int l, int r) {
return upper_bound(g[x].begin(), g[x].end(), r) - lower_bound(g[x].begin(), g[x].end(), l);
}
int query(int ql,int qr){
int res=inf,cnt=0;
if(belong[ql]==belong[qr]){
rep(i,ql,qr){
int tmp=Find(a[i],ql,qr);
if(cnt<tmp) cnt=tmp,res=a[i];
else if(cnt==tmp&&a[i]<res) res=a[i];
}
return res;
}
res=dp[belong[ql]+1][belong[qr]-1];
cnt=Find(res,ql,qr);
rep(i,ql,r[belong[ql]]){
int tmp=Find(a[i],ql,qr);
if(cnt<tmp) cnt=tmp,res=a[i];
else if(cnt==tmp&&a[i]<res) res=a[i];
}
rep(i,l[belong[qr]],qr){
int tmp=Find(a[i],ql,qr);
if(cnt<tmp) cnt=tmp,res=a[i];
else if(cnt==tmp&&a[i]<res) res=a[i];
}
return res;
}

int main(){
n=read;
block=150;
int num=n/block;
if(n%block) num++;

rep(i,1,num) l[i]=(i-1)*block+1,r[i]=i*block;

rep(i,1,n) a[i]=read,b[i]=a[i];

sort(b+1,b+1+n);

m=unique(b+1,b+1+n)-(b);

rep(i,1,n){
a[i]=lower_bound(b+1,b+m,a[i])-(b);
g[a[i]].push_back(i);
belong[i]=(i-1)/block+1;
}

for(int i=1;i<=num;i++){
int res=0,cnt=0;
memset(mp,0,sizeof mp);
for(int j=(i-1)*block+1;j<=n;j++){
mp[a[j]]++;
if(mp[a[j]]>cnt) cnt=mp[a[j]],res=a[j];
else if(mp[a[j]]==cnt&&a[j]<res) res=a[j];
dp[i][belong[j]]=res;
}
}


rep(i,1,n){
int ql=read,qr=read;
write(b[query(ql,qr)]);
puts("");
}


return 0;
}


举报

相关推荐

0 条评论