题意:给出区间内的最小众数

思路:分块,离散化每个数,开vector记录每个数p出现的位置,这样就能二分出L,R以内p的个数了。众数有一个性质,用mode(a)表示集合a的众数,那么mode(a∪b) ∈ mode(a)∪b 。那么我先预处理出任意两块的众数f[i][j],这样众数就是f[i][j]和旁边两块数中的其中一个了,直接遍历这些数即可。

block不能开方,开30能过。都靠玄学....

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;
struct Block{
int l, r;
}b[maxn];
int a[maxn], belong[maxn];
int f[10000][10000]; //i~j块的众数是
int num[maxn];
int n, block;
vector<int> vv;
vector<int> pos[maxn];
void init(){
for(int i = 1; i <= belong[n]; i++){ //暴力计算f数组
for(int j = 0; j <= vv.size(); j++) num[j] = 0;
int mode = INF, NUM = 0;
for(int j = b[i].l; j <= n; j++){
num[a[j]]++;
if(num[a[j]] > NUM || (num[a[j]] == NUM && a[j] < mode)){
mode = a[j];
NUM = num[a[j]];
}
f[i][belong[j]] = mode;
}
}
}
int getNum(int l, int r, int v){
int t = upper_bound(pos[v].begin(), pos[v].end(), r) - lower_bound(pos[v].begin(), pos[v].end(), l);
return t;
}
int query(int l, int r){
int bl = belong[l], br = belong[r];
int ans = INF, NUM = 0;
if(bl == br){
for(int i = l; i <= r; i++){
int tot = getNum(l, r, a[i]);
if(tot > NUM || (tot == NUM && a[i] < ans)){
ans = a[i];
NUM = tot;
}
}
}
else{
for(int i = l; i <= b[bl].r; i++){
int tot = getNum(l, r, a[i]);
if(tot > NUM || (tot == NUM && a[i] < ans)){
ans = a[i];
NUM = tot;
}
}
if(bl + 1 <= br - 1){
int v = f[bl + 1][br - 1];
int tot = getNum(l, r, v);
if(tot > NUM || (tot == NUM && v < ans)){
ans = v;
NUM = tot;
}
}
for(int i = b[br].l; i <= r; i++){
int tot = getNum(l, r, a[i]);
if(tot > NUM || (tot == NUM && a[i] < ans)){
ans = a[i];
NUM = tot;
}
}
}
return vv[ans - 1];
} int main(){
scanf("%d", &n);
vv.clear();
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
vv.push_back(a[i]);
} sort(vv.begin(), vv.end());
vv.erase(unique(vv.begin(), vv.end()), vv.end());
for(int i = 1; i <= n; i++){
a[i] = lower_bound(vv.begin(), vv.end(), a[i]) - vv.begin() + 1;
}
for(int i = 0; i <= vv.size(); i++) pos[i].clear(); block = 30;
for(int i = 1; i <= n; i++){
belong[i] = (i - 1) / block + 1;
pos[a[i]].push_back(i);
}
for(int i = 1; i <= belong[n]; i++){
b[i].l = (i - 1) * block + 1;
b[i].r = b[i].l + block - 1;
}
b[belong[n]].r = n; init();
for(int i = 1; i <= n; i++){
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", query(l, r));
}
return 0;
}

LOJ6285 数列分块入门9(分块 区间众数)题解的更多相关文章

  1. loj 数列分块入门 6 9(区间众数)

    6 题意 给出一个长为\(n\)的数列,以及\(n\)个操作,操作涉及单点插入,单点询问,数据随机生成. 题解 参考:http://hzwer.com/8053.html 每个块内用一个\(vecto ...

  2. LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)

    #6283. 数列分块入门 7 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2   题目描述 给出 ...

  3. LOJ #6281. 数列分块入门 5-分块(区间开方、区间求和)

    #6281. 数列分块入门 5 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 5   题目描述 给出 ...

  4. LOJ #6280. 数列分块入门 4-分块(区间加法、区间求和)

    #6280. 数列分块入门 4 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论   题目描述 给出一个 ...

  5. LOJ #6279. 数列分块入门 3-分块(区间加法、查询区间内小于某个值x的前驱(比其小的最大元素))

    #6279. 数列分块入门 3 内存限制:256 MiB时间限制:1500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 3   题目描述 给 ...

  6. LOJ #6278. 数列分块入门 2-分块(区间加法、查询区间内小于某个值x的元素个数)

    #6278. 数列分块入门 2 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 6   题目描述 给出 ...

  7. LOJ #6277. 数列分块入门 1-分块(区间加法、单点查询)

    #6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2   题目描述 给出 ...

  8. LibreOJ 6280 数列分块入门 4(分块区间加区间求和)

    题解:分块的区间求和比起线段树来说实在是太好写了(当然,复杂度也高)但这也是没办法的事情嘛.总之50000的数据跑了75ms左右还是挺优越的. 比起单点询问来说,区间询问和也没有复杂多少,多开一个su ...

  9. LibreOJ 6281 数列分块入门 5(分块区间开方区间求和)

    题解:区间开方emmm,这马上让我想起了当时写线段树的时候,很显然,对于一个在2^31次方以内的数,开方7-8次就差不多变成一了,所以我们对于每次开方,如果块中的所有数都为一了,那么开方也没有必要了. ...

  10. #6284. 数列分块入门 8(区间询问等于一个数 cc 的元素,并将这个区间的所有元素改为 c)

    题目链接:https://loj.ac/problem/6284 题目大意:中文题目 具体思路:还是和sqrt那个题的思路相同的,标记每一块的值是不是相同的,注意lazy下标的下放. AC代码: #i ...

随机推荐

  1. vue3.0 composition API

    一.Setup函数 1.创建时间:组件创建之前被调用,优先与created被调用,this指向的实例为window,created所指向的实例为proxy 2.this指向:不会指向组件实例 3.参数 ...

  2. JavaScript中创建数组的方式!

    JavaScript中创建数组的方式! 利用数组字面量 // 1 直接量 console.log(Array.prototype); var arr = [1, 2, 4, 87432]; // 注意 ...

  3. day03 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数

    本节内容 1. 函数基本语法及特性 2. 参数与局部变量 3. 返回值 嵌套函数 4.递归 5.匿名函数 6.函数式编程介绍 7.高阶函数 8.内置函数 温故知新 1. 集合 主要作用: 去重 关系测 ...

  4. code-server Command ' ' not found

    由于通过一些特殊的方式登录linux用户后,全局变量不会自动加载,需要在 vscode 的 bash terminal手动读取 输入 source /etc/profile 或者vim ~/.bash ...

  5. get uuid

    https://wx2.qq.com/?&lang=zh_CN /** * 启动二维码登录 */ function doQrcodeLogin() { loginFactory.getUUID ...

  6. socket创建和结束

    什么是进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在早期面向进程设计的计算机结构中,进程是程序的基本执行实体: ...

  7. SpringMVC听课笔记(十二:文件的上传)

    1.Spring MVC为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver实现的.Spring用Jakarta Commons FileUpload技术实现了一个M ...

  8. java 静态资源,非静态资源,父类子类,构造方法之间的初始化循序

    java面试经常被问静态资源,非静态资源,父类子类,构造方法之间的执行顺序.下面添加两个类做个测试 class Parent { // 静态变量 public static String p_Stat ...

  9. 常用DOS命令及其用法

    md ​ 1.作用:建立子目录 ​ 2.用法:md [盘符:] [路径名] ①盘符:指定要建立子目录的磁盘驱动器字母,若省略,则为当前驱动器: ②路径名:要建立的子目录的上级目录名,若缺省则建在当前目 ...

  10. (十七)整合 Zookeeper组件,管理架构中服务协调

    整合 Zookeeper组件,管理架构中服务协调 1.Zookeeper基础简介 1.1 基本理论 1.2 应用场景 2.安全管理操作 2.1 操作权限 2.2 认证方式: 2.3 Digest授权流 ...