BZOJ2724:[Violet 6]蒲公英——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=2724

输入格式
第一行两个整数n,m,表示有n株蒲公英,m次询问。
接下来一行 n 个空格分隔的整数ai,表示蒲公英的种类
再接下来m行每行两个整数l0,r0,我们令上次询问的结果为x(如果这是第一次询问,则x=0)。
令l=(l0+x-1)mod n +1,r=(r0+x-1)mod n +1,如果l>r,则交换l,r。
最终的询问区间为[l,r]。
输出格式
输出m行。每行一个整数,表示每次询问的结果。
样例输入
6 3
1 2 3 2 1 2
1 5
3 6
1 5
样例输出
1
2
1
——————————————————————————————————
分块板子题。
我们首先离散化,然后分块分成sqrt(N)长度的块,然后预处理一下东西:
1.sum[i][j]:前j块i元素出现次数。
2.ans[i][j]:i~j块的众数。
这两个操作都靠暴力(桶排序)解决,复杂度显然O(NsqrtN)。
然后就是惊心动魄的询问时间:
1.跨度<=2个块长度:直接暴力。
2.跨度>2个块长度:显然区间一定跨过了至少一些/个连续的块,这些连续的块的众数我们能求出来,然后我们的答案显然就是:
1.这个众数。
2.非整块区间内的数。
对于2暴力(桶排序)即可,然后和1比较,注意处理2的个数的时候不要忘了加上该数在连续的块中出现的个数。
简单证明:我们只需要证明非连续的块的众数的数且没出现在非整块区间内的数一定不是众数。
这十分显然,因为它本身不是非连续的块的众数,个数一定比该众数小,又没出现在非整块区间内,所以个数一定比该众数小,则它一定不可能是众数。
#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
const int N=;
const int SQRTN=;
const int INF=;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
int n,m,lim,s,cnt,a[N],b[N],bl[SQRTN],br[SQRTN];
int sum[N][SQRTN],ans[N][SQRTN],t[N];
bool vis[N];
inline void LSH(){
sort(b+,b+lim+);
lim=unique(b+,b+lim+)-b-;
for(int i=;i<=n;i++){
a[i]=lower_bound(b+,b+lim+,a[i])-b;
}
return;
}
inline void intoblock(){
for(int i=;i<=n;i++){
if(i%s==){br[cnt]=i-;bl[++cnt]=i;}
}
br[cnt]=n;bl[cnt+]=n+;
return;
}
inline void init(){
for(int i=;i<=cnt;i++){
for(int j=bl[i];j<=n;j++)t[a[j]]=;
int maxn=-INF,cur;
for(int j=i;j<=cnt;j++){
for(int k=bl[j];k<=br[j];k++){
int c=++t[a[k]];
if(c>maxn)maxn=c,cur=a[k];
else if(c==maxn&&a[k]<cur)cur=a[k];
}
ans[i][j]=cur;
}
for(int j=;j<=lim;j++)sum[j][i]=sum[j][i-];
for(int j=bl[i];j<=br[i];j++){
sum[a[j]][i]++;
}
}
return;
}
inline int query(int l,int r){
memset(vis,,sizeof(vis));
memset(t,,sizeof(t));
int maxn=-INF,cur;
if(r-l+<=*s){
for(int i=l;i<=r;i++){
vis[a[i]]=;
t[a[i]]++;
}
for(int i=l;i<=r;i++){
if(vis[a[i]]){
if(t[a[i]]>maxn)maxn=t[a[i]],cur=a[i];
else if(t[a[i]]==maxn&&a[i]<cur)cur=a[i];
}
}
return cur;
}
int L=(l-)/s+,R=(r-)/s+;
cur=ans[L+][R-];
maxn=sum[cur][R-]-sum[cur][L];
for(int i=l;i<=br[L];i++){
vis[a[i]]=;
t[a[i]]++;
}
for(int i=bl[R];i<=r;i++){
vis[a[i]]=;
t[a[i]]++;
}
for(int i=l;i<=br[L];i++){
if(vis[a[i]]){
int c=t[a[i]]+sum[a[i]][R-]-sum[a[i]][L];
if(c>maxn)maxn=c,cur=a[i];
else if(c==maxn&&a[i]<cur)cur=a[i];
}
}
for(int i=bl[R];i<=r;i++){
if(vis[a[i]]){
int c=t[a[i]]+sum[a[i]][R-]-sum[a[i]][L];
if(c>maxn)maxn=c,cur=a[i];
else if(c==maxn&&a[i]<cur)cur=a[i];
}
}
return cur;
}
int main(){
n=read();m=read();s=sqrt(n);
for(int i=;i<=n;i++)a[i]=b[++lim]=read();
LSH();
intoblock();
init();
int pre=;
for(int i=;i<=m;i++){
int l=(read()+pre-)%n+,r=(read()+pre-)%n+;
if(l>r)swap(l,r);
printf("%d\n",pre=b[query(l,r)]);
}
return ;
}
BZOJ2724:[Violet 6]蒲公英——题解的更多相关文章
- [BZOJ2724][Violet 6]蒲公英
[BZOJ2724][Violet 6]蒲公英 试题描述 输入 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 输出 输入示 ...
- BZOJ2724 [Violet 6]蒲公英 分块
原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...
- bzoj2724: [Violet 6]蒲公英(离散化+分块)
我好弱啊..这题调了2天QwQ 题目大意:给定一个长度为n(n<=40000)的序列,m(m<=50000)次询问l~r之间出现次数最多的数.(区间众数) 这题如果用主席树就可以不用处理一 ...
- bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式
这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...
- 【分块】bzoj2724 [Violet 6]蒲公英
分块,离散化,预处理出: ①前i块中x出现的次数(差分): ②第i块到第j块中的众数是谁,出现了多少次. 询问的时候,对于整块的部分直接获得答案:对于零散的部分,暴力统计每个数出现的次数,加上差分的结 ...
- bzoj2724: [Violet 6]蒲公英(分块)
传送门 md调了一个晚上最后发现竟然是空间开小了……明明算出来够的…… 讲真其实我以前不太瞧得起分块,觉得这种基于暴力的数据结构一点美感都没有.然而今天做了这道分块的题才发现分块的暴力之美(如果我空间 ...
- 【BZOJ2724】[Violet 6]蒲公英 分块+二分
[BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...
- BZOJ 2724: [Violet 6]蒲公英
2724: [Violet 6]蒲公英 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 1633 Solved: 563[Submit][Status ...
- BZOJ 2724: [Violet 6]蒲公英( 分块 )
虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...
随机推荐
- 深入解析UUID及其应用(转载)
UUID 编辑 UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Founda ...
- 错误码:2003 不能连接到 MySQL 服务器在 (10061)
今天在ubuntu上安装了mysql服务器,在windows上用客户端软件连接mysql服务器时,出现错误: 错误码: 不能连接到 MySQL 服务器在 () 折腾来折腾去没搞好,防火墙也关了,330 ...
- 怎样通过Qt编写C/C++代码查询当前Linux的版本号?
遇到一个问题:如题. 我的开发环境是:嵌入式ARM + Linux系统 + Qt 4.5 + C/C++ 现在需要查询 当前Linux系统的版本号. 问题: 1)Qt 4.5 提供怎样的API来获取? ...
- TPO-14 C2 Prepare for a career in journalism
TPO-14 C2 Prepare for a career in journalism 第 1 段 1.Listen to a conversation between a student and ...
- Linux 文件的常识
文件 文件的分类 文件 目录 链接 区分办法,ls -la 查看 十个标志符中的第一个 如:drwxrwxr-x. 2 normal normal 4096 8月 31 23:43 dir 目录是d ...
- laravel 的DB::raw() 语法使用
z之前在项目中遇到一个问题,复杂的sql查询,用laravel的查询构造器,非常的不方便,各种查询条件拼接一长串拼得脑瓜疼:然后想使用原生的sql语句来查询,然后又使用不了laravel的pagina ...
- JAVA基础学习之路(十)this关键字
class Book { String name; int price; int num;//构造方法之间的互相调用解决了代码的重复问题,但是一定要留出口 public Book() { ,); } ...
- JDK源码分析:Short.java
Short是基本数据类型short的包装类. 1)声明部: public final class Short extends Number implements Comparable<Short ...
- java学习过程小问题
一:基本的需要注意点(基础语句); package my; public class hello { public static void main(String[] args) { // TODO ...
- dice2win
触发交易 转0个 https://etherscan.io/tx/0x784e80167353a886183106cbe3bd15e614cafdb5d6885ccd101177aa0f937a36 ...