题面。

许久以前我还不怎么去机房的时候,一位大佬好像一直在做这道题,他称这道题目为“大分块”。

其实这道题目的思想不只可以用于处理区间众数,还可以处理很多区间数值相关问题。

让我们在线处理区间众数。

数据范围1e5,考虑分块。

先对蒲公英种类离散化。

预处理

预处理出两个数组。

一个数组sum[ i ][ j ]表示第j种颜色到第i个分块的前缀和。

另一个数组 zhongshu[ i ][ j ]表示第i个分块到第j个分块这个区间内的众数。

维护这两个操作时间复杂度都不能超过n3/2。

第一个数组很好维护,输入的时候将输入位置对应分块的相应种类加一,然后跑一遍前缀和即可,时间复杂度n*n1/2。

维护第二个数组,我们需要先枚举起始分块。

从起始分块开始,枚举终点分块,每枚举一个终点分块,更新这个分块内元素对于区间众数的贡献。

建立一个数组tmp[ i ]作为辅助数组表示颜色i出现次数。

for(int i=1;i<=get_pos(n);i++){//枚举起始分块
int mx=0;//从当前这个起始分块开始,到终点分块位置的众数for(int j=i;j<=get_pos(n);j++)//枚举终点分块
for(int k=(j-1)*len+1;k<=min(j*len,n);k++){
tmp[a[k]]++;//当前元素出现次数加一
if(tmp[a[k]]>tmp[mx])//若当前元素出现次数大于当前处理区间众数的出现次数,则将众数修改为当前元素
mx=a[k];
if(!(tmp[a[k]]^tmp[mx]))//若当前元素与当前处理区间众数出现次数相等,则取编号小的为众数
mx=min(mx,a[k]);
}
b_mos[i][j]=mx;//从分块i到分块j的众数就是mx
}
for(int j=0;j<=ntot;j++)//清空辅助数组
tmp[j]=0;
}

时间复杂度为n1/2 *(n+n1/2*n1/2),即n3/2。

处理询问

对于询问的l,r,算出其所处分块lb,rb。

若l与r在同一分块或在相邻块内,可以暴力求出众数,时间复杂度n1/2。

int get_vio(){//vio指violent
int mx=0;
for(int i=l;i<=r;i++){
tmp[a[i]]++;
if(tmp[a[i]]>tmp[mx])//按比较规则进行更新。
mx=a[i];
if(!(tmp[a[i]]^tmp[mx]))
mx=min(mx,a[i]);
}
for(int i=l;i<=r;i++)
tmp[a[i]]--;
return mx;
}

若l与r所在分块中间相隔了至少一个分块,那么所询问区间的众数只有两种可能。

  1. 中间那一段分块的众数
  2. 左端点所在块与右端点所在块内的数

不难理解。

对于中间那一段分块内的数,如果它们的出现次数要超过中间那一段分块内的众数,那么它们必须要在左端点所在块和右端点所在块内出现。

先将中间那一段分块的众数设为答案,再对左端点和右端点所在块内的数统计出现次数并更新答案即可。

int get_tim(int x){
return tmp[x]+b_sum[rb-1][x]-b_sum[lb][x];//计算某数的总出现次数
}
int get_q(){
int mx=b_mos[lb+1][rb-1];//先将答案设为中间那一段分块内的众数
for(int i=l;i<=lb*len;i++){
tmp[a[i]]++;
if(get_tim(a[i])>get_tim(mx))//按照比较规则更新答案
mx=a[i];
if(get_tim(a[i])==get_tim(mx))
mx=min(mx,a[i]);
}
for(int i=(rb-1)*len+1;i<=r;i++){
tmp[a[i]]++;
if(get_tim(a[i])>get_tim(mx))
mx=a[i];
if(get_tim(a[i])==get_tim(mx))
mx=min(mx,a[i]);
}
for(int i=l;i<=lb*len;i++)//清空辅助数组
tmp[a[i]]--;
for(int i=(rb-1)*len+1;i<=r;i++)
tmp[a[i]]--;
return mx;
}

处理单词询问时间复杂度为n1/2。

算法整体复杂度为(m+n)*n1/2,即n3/2,可以通过本题。

类似的题目还有  洛谷P4135 。

#include<bits/stdc++.h>
using namespace std;
const int h=40010;
const int b_h=210;
int len;
int get_pos(int x){//得到某个位置所在分块编号
return (x-1)/len+1;
}
int n,m;
int a[h],line[h];
int ntot=0,num[h];
map<int,int>rk;
int tmp[h];
int b_mos[b_h][b_h];
int b_sum[b_h][h];
void get_pre(){
for(int i=1;i<=get_pos(n);i++)
for(int j=1;j<=ntot;j++)
b_sum[i][j]+=b_sum[i-1][j];
for(int i=1;i<=get_pos(n);i++){
int mx=0;
for(int j=i;j<=get_pos(n);j++){
for(int k=(j-1)*len+1;k<=min(j*len,n);k++){
tmp[a[k]]++;
if(tmp[a[k]]>tmp[mx])
mx=a[k];
if(!(tmp[a[k]]^tmp[mx]))
mx=min(mx,a[k]);
}
b_mos[i][j]=mx;
}
for(int j=0;j<=ntot;j++)
tmp[j]=0;
}
}
int l,r,lb,rb,lst=0,ans;
int get_vio(){
int mx=0;
for(int i=l;i<=r;i++){
tmp[a[i]]++;
if(tmp[a[i]]>tmp[mx])
mx=a[i];
if(tmp[a[i]]==tmp[mx])
mx=min(mx,a[i]);
}
for(int i=l;i<=r;i++)
tmp[a[i]]--;
return mx;
}
int get_tim(int x){//计算一个数的出现次数
return tmp[x]+b_sum[rb-1][x]-b_sum[lb][x];
}
int get_q(){
int mx=b_mos[lb+1][rb-1];
for(int i=l;i<=lb*len;i++){
tmp[a[i]]++;
if(get_tim(a[i])>get_tim(mx))
mx=a[i];
if(get_tim(a[i])==get_tim(mx))
mx=min(mx,a[i]);
}
for(int i=(rb-1)*len+1;i<=r;i++){
tmp[a[i]]++;
if(get_tim(a[i])>get_tim(mx))
mx=a[i];
if(get_tim(a[i])==get_tim(mx))
mx=min(mx,a[i]);
}
for(int i=l;i<=lb*len;i++)
tmp[a[i]]--;
for(int i=(rb-1)*len+1;i<=r;i++)
tmp[a[i]]--;
return mx;
}
int main(){
scanf("%d%d",&n,&m);
len=sqrt(n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),line[i]=a[i];
sort(line+1,line+n+1);
for(int i=1;i<=n;i++)//离散化
if(line[i]!=line[i-1])
rk[line[i]]=++ntot,num[ntot]=line[i]; for(int i=1;i<=n;i++)
a[i]=rk[a[i]]; for(int i=1;i<=n;i++)
b_sum[get_pos(i)][a[i]]++;
get_pre();
for(int i=1;i<=m;i++){
scanf("%d%d",&l,&r);
l=(l+lst-1)%n+1,r=(r+lst-1)%n+1;
if(l>r)
swap(l,r);
lb=get_pos(l),rb=get_pos(r);
if(lb>=rb-1)
ans=get_vio();
else
ans=get_q();
printf("%d\n",num[ans]),lst=num[ans];
}
return 0;
}

完整代码

洛谷P4168 蒲公英 分块处理区间众数模板的更多相关文章

  1. 洛谷P4168 蒲公英 [Violet] 分块

    题解:分块+离散化 解题报告: 一个分块典型题呢qwq还是挺妙的毕竟是道黑题 然,然后发现忘记放链接了先放链接QAQ 有两三种解法,都港下qwq 第一个是O(n5/3)的复杂度,谢总说不够优秀没有港, ...

  2. 【洛谷 P4168】[Violet]蒲公英(分块)

    题目链接 题目大意:给定\(n\)个数和\(m\)个求区间众数的询问,强制在线 这题我\(debug\)了整整一个下午啊..-_- 从14:30~16:45终于\(debug\)出来了,\(debug ...

  3. 洛谷 P4168 [Violet] 蒲公英

    历尽千辛万苦终于AC了这道题目... 我们考虑1个区间\([l,r]\), 被其完整包含的块的区间为\([L,R]\) 那么众数的来源? 1.\([l,L)\)或\((R,r]\)中出现的数字 2.\ ...

  4. 洛谷P1880 石子合并(区间DP)(环形DP)

    To 洛谷.1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1 ...

  5. 洛谷 P5469 - [NOI2019] 机器人(区间 dp+拉格朗日插值)

    洛谷题面传送门 神仙题,放在 D1T2 可能略难了一点( 首先显然对于 P 型机器人而言,将它放在 \(i\) 之后它会走到左边第一个严格 \(>a_i\) 的位置,对于 Q 型机器人而言,将它 ...

  6. 洛谷P1063 能量项链(区间DP)(环形DP)

    To 洛谷.1063 能量项链 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的 ...

  7. 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器

    刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...

  8. [洛谷P4768] [NOI2018]归程 (kruskal重构树模板讲解)

    洛谷题目链接:[NOI2018]归程 因为题面复制过来有点炸格式,所以要看题目就点一下链接吧\(qwq\) 题意: 在一张无向图上,每一条边都有一个长度和海拔高度,小\(Y\)的家在\(1\)节点,并 ...

  9. 洛谷P1919 A*B problem 快速傅里叶变换模板 [FFT]

    题目传送门 A*B problem 题目描述 给出两个n位10进制整数x和y,你需要计算x*y. 输入输出格式 输入格式: 第一行一个正整数n. 第二行描述一个位数为n的正整数x. 第三行描述一个位数 ...

随机推荐

  1. 【java】非常多!学习路径24-总结目前所有知识(上)

    感谢sikiedu.com的siki老师.几年前就开始看siki的课程,最近突然想写这个笔记系列,顺便回顾一下这些基础的知识,同时也希望能帮助到一些人,有问题一起交流哈. 全文共十章,大约1.5万字, ...

  2. [WPF] 使用 HandyControl 的 CirclePanel 画出表盘刻度

    1. 前言 最近需要一个 WPF 的表盘控件,之前 Cyril-hcj 写过一篇不错的博客 <WPF在圆上画出刻度线>,里面介绍了一些原理及详细实现的代码: double radius = ...

  3. 详谈 MySQL 8.0 原子 DDL 原理

    柯煜昌 青云科技研发顾问级工程师 目前从事 RadonDB 容器化研发,华中科技大学研究生毕业,有多年的数据库内核开发经验. 文章字数 3800+,阅读时间 15 分钟 背景 MySQL 5.7 的字 ...

  4. LFS(Linux From Scratch)构建过程全记录(七):进入Chroot并构建临时工具

    写在前面 本章将完成临时系统构建的最后缺失部分和各种包构建所需的工具. 解决了所有循环依赖关系后,就可以使用与主机操作系统完全隔离的"chroot"环境进行构建. 注意:接下来的指 ...

  5. docker学习笔记-常用镜像相关命令

    docker images # 1.使用 [root@iZbp13qr3mm4ucsjumrlgqZ ~]# docker images REPOSITORY TAG IMAGE ID CREATED ...

  6. 《Java基础——break与continue用法详解》

    Java基础--break与continue用法详解       1. break语句: 规则: 1. 仅用于循环语句和switch语句当中,用于跳出循环. 2. 当只有一层循环时,则直接跳出循环,不 ...

  7. Java中的SPI原理浅谈

    在面向对象的程序设计中,模块之间交互采用接口编程,通常情况下调用方不需要知道被调用方的内部实现细节,因为一旦涉及到了具体实现,如果需要换一种实现就需要修改代码,这违反了程序设计的"开闭原则& ...

  8. 【学习笔记】Vin-Mono论文阅读笔记(一)

    VINS-Mono 概述 VINS-Mono VINS-Mono是由一个单目相机和一个低成本IMU组成的鲁棒通用的单目视觉惯性系统.通过融合预积分的IMU测量值和特征观测值来获得高精度的视觉惯性里程计 ...

  9. OSF--网络类型

    ABR:区域边界路由器ASBR:自治区域系统边界路由器区域部署原则:    存在vlink本地网络一定是有问题的.他只是作为一种过度技术,在vlink里无法实现认证! 配置:   [r2-ospf-a ...

  10. PAT (Basic Level) Practice 1003 我要通过!分数 20

    "答案正确"是自动判题系统给出的最令人欢喜的回复.本题属于 PAT 的"答案正确"大派送 -- 只要读入的字符串满足下列条件,系统就输出"答案正确&q ...