Loj 6285. 数列分块入门 9

链接:

https://loj.ac/problem/6285

思路:

离散化处理下就好了,具体解释在代码里、

ps:

小新新别看了,你学不会的

实现代码:

#include<bits/stdc++.h>
using namespace std;
const int M = 1e5 + 10;
int n,block,idx,a[M],bl[M],f[510][510],val[M],cnt[M];
vector<int>ve[M];
void pre(int x){  //预处理
    memset(cnt,0,sizeof(cnt));
    int mx = 0, ans = 0;
    for(int i = (x - 1)*block+1;i <= n;i ++){
        cnt[a[i]]++;
        int t = bl[i];
        if(cnt[a[i]] > mx||(cnt[a[i]]==mx&&val[a[i]]<val[ans])) //如果在当前区间出现次数比最大值或者和最大值一样但是值比最大值小,那么更新最大值
            ans = a[i],mx = cnt[a[i]];
        f[x][t] = ans;  //代表 x块 到 t块中的最小众数
    }
}

int query(int l,int r,int x){  //在ve[ai]二分寻找在l,r区间的a[i]的数量
    int t = upper_bound(ve[x].begin(),ve[x].end(),r) - lower_bound(ve[x].begin(),ve[x].end(),l);
    return t;
}

int query(int l,int r){
    int ans,mx;
    ans = f[bl[l]+1][bl[r]-1]; //完整块的查询
    mx = query(l,r,ans);
    //非完整块的查询
    for(int i = l;i <= min(bl[l]*block,r);i ++){
        int t = query(l,r,a[i]);
        if(t > mx||(t == mx&&val[a[i]] < val[ans]))
            ans = a[i],mx = t;
    }
    if(bl[l] != bl[r]){
        for(int i = (bl[r]-1)*block+1;i <= r;i ++){
            int t = query(l,r,a[i]);
            if(t > mx||(t == mx&&val[a[i]] < val[ans]))
                ans = a[i],mx = t;
        }
    }
    return ans;
}
map<int,int>mp;
int main()
{
    int l,r;
    scanf("%d",&n);
    block = sqrt(n);
    for(int i = 1;i <= n;i ++){
        scanf("%d",&a[i]);
        if(!mp[a[i]]){
            mp[a[i]] = ++idx;   //离散化
            val[idx] = a[i];    //val数组储存离散化之前的值
        }
        a[i] = mp[a[i]]; //离散化
        ve[a[i]].push_back(i);  //将每个a[i]出现的下标存到a[i]对应的vecotr里
    }
    for(int i = 1;i <= n;i ++) bl[i] = (i - 1)/block + 1;
    for(int i = 1;i <= bl[n];i ++)  pre(i); //预处理每一个块
    for(int i = 1;i <= n;i ++) {
        scanf("%d%d",&l,&r);
        if(l > r) swap(l,r);
        printf("%d
",val[query(l,r)]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/kls123/p/9379256.html