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\n",val[query(l,r)]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/kls123/p/9379256.html

时间: 2024-08-30 12:09:07

Loj 6285. 数列分块入门 9的相关文章

loj#6285 数列分块入门 9 ( 回 滚 )

题目 :  链接 :https://loj.ac/problem/6285 题意:给出一个长为 n的数列,以及 n个操作,操作涉及询问区间的最小众数. 思路:虽然这不是一道 回滚莫队题,就是 暴力分块 的题, 但是 还是 可以用回滚莫队 写滴,好像大部分题解都是 暴力分块. #include<bits/stdc++.h> #define LL long long #define ULL unsigned long long #define rep(i,j,k) for(int i=j;i<

LOJ#6284. 数列分块入门 8

#6284. 数列分块入门 8 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论 1 测试数据 题目描述 给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间询问等于一个数 ccc 的元素,并将这个区间的所有元素改为 ccc. 输入格式 第一行输入一个数字 nnn. 第二行输入 nnn 个数字,第 i 个数字为 aia_ia?i??,以空格隔开. 接下来输入 nnn 行询问,每行输入三个数字 ll

LOJ6277~6285 数列分块入门

Portals 分块需注意的问题 数组大小应为\(N+\sqrt N\),因为最后一个块可能会超出\(N\)的范围.改成记录\(blk,fr,to\)就不用担心这个了 当操作的区间在一个块内时,要特判成暴力修改. 要清楚什么时候应该+tag[t] 最后一个块是越界的,注意是否有影响 数列分块入门 1 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及区间加法,单点查值. //数列分块入门 1 #include <cstdio> #include <cmath> inlin

Loj 6279. 数列分块入门 3

题目描述 给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的前驱(比其小的最大元素). 输入格式 第一行输入一个数字 nnn. 第二行输入 nnn 个数字,第 iii 个数字为 aia_iai?,以空格隔开. 接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt.lll.rrr.ccc,以空格隔开. 若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l, r][l,r] 的之间的数字

Loj 6277 数列分块入门 1

题目链接:https://loj.ac/problem/6277 题面: 题目描述 给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,单点查值. 输入格式 第一行输入一个数字 nnn. 第二行输入 nnn 个数字,第 iii 个数字为 aia_ia?i??,以空格隔开. 接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt.lll.rrr.ccc,以空格隔开. 若 opt=0\mathrm{opt} = 0opt=0,表示将位于 [l,r][l,

LibreOJ 6285. 数列分块入门 9

题目链接:https://loj.ac/problem/6285 其实一看到是离线,我就想用莫队算法来做,对所有询问进行分块,但是左右边界移动的时候,不会同时更新数字最多的数,只是后面线性的扫了一遍,所以还有百分之12的样例过不了. 然后看了别人分块,是先对所有零散的数字编号(这个应该是所谓离散化),用vector[i]存储编号为i的数字所有出现的位置,因为从0到n,所以里面的值是升序的,我们先对块与块之间数字最多的数进行计算(预处理),在查询的时候查询[l,r]之间的数,把区间分成三块,左边不

LOJ#6278. 数列分块入门 2

内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论测试数据 题目描述 给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间加法,询问区间内小于某个值 xxx 的元素个数. 输入格式 第一行输入一个数字 nnn. 第二行输入 nnn 个数字,第 i 个数字为 aia_ia?i??,以空格隔开. 接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt.lll.rrr.ccc,

LOJ#6281. 数列分块入门 5

内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论 1 测试数据 题目描述 给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及区间开方,区间求和. 输入格式 第一行输入一个数字 nnn. 第二行输入 nnn 个数字,第 i 个数字为 aia_ia?i??,以空格隔开. 接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt.lll.rrr.ccc,以空格隔开. 若 opt=

LOJ#6282. 数列分块入门 6

内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计讨论测试数据 题目描述 给出一个长为 nnn 的数列,以及 nnn 个操作,操作涉及单点插入,单点询问,数据随机生成. 输入格式 第一行输入一个数字 nnn. 第二行输入 nnn 个数字,第 i 个数字为 aia_ia?i??,以空格隔开. 接下来输入 nnn 行询问,每行输入四个数字 opt\mathrm{opt}opt.lll.rrr.ccc,以空格隔开. 若