【题目链接】

https://www.lydsy.com/JudgeOnline/problem.php?id=2724

【算法】

分块算法在线维护区间众数

分块算法的精髓就在于 : 大段维护,局部朴素

这一题,我们可以将序列分成T段,那么每一段的长度就是(N/T)

对于每个询问,设l处于第p段,r处于第q段,那么 :

若p = q,用朴素算法计算出区间众数即可

否则,将这个序列分为三段 :

1.[L,R[p]] 2. [L[p+1],R[q-1]] 3. [L[q],r]

显然,区间众数只可能是 [L[p+1],R[q-1]]中的众数或[L,R[p]]中的一个数,或[L[q],r]中的一个数

不妨预处理所有以“段边界”为端点每个数出现的次数和区间众数

    当T取sqrt3(N)(开三次方)时,时间复杂度是非常优秀的 : O(n^(5/3))

【代码】

#include<bits/stdc++.h>
using namespace std;
#define MAXN 40010
const int INF = 2e9; int i,j,k,n,m,l,r,l0,r0,lastans,t,block,len;
int a[MAXN],val[MAXN],L[],R[],pos[MAXN],rk[MAXN];
int cnt[][][MAXN],mx[][],d[][]; inline int query(int l,int r)
{
int i;
static int sum[MAXN];
int mx = ,ret = ;
int p = pos[l],q = pos[r];
if (p == q)
{
for (i = l; i <= r; i++)
{
sum[rk[i]]++;
if (sum[rk[i]] > mx || (sum[rk[i]] == mx && rk[i] < ret))
{
mx = sum[rk[i]];
ret = rk[i];
}
}
for (i = l; i <= r; i++) sum[rk[i]]--;
return ret;
} else
{
ret = d[p+][q-];
mx = cnt[p+][q-][ret];
for (i = l; i <= R[p]; i++)
{
cnt[p+][q-][rk[i]]++;
if (cnt[p+][q-][rk[i]] > mx || (cnt[p+][q-][rk[i]] == mx && rk[i] < ret))
{
mx = cnt[p+][q-][rk[i]];
ret = rk[i];
}
}
for (i = L[q]; i <= r; i++)
{
cnt[p+][q-][rk[i]]++;
if (cnt[p+][q-][rk[i]] > mx || (cnt[p+][q-][rk[i]] == mx && rk[i] < ret))
{
mx = cnt[p+][q-][rk[i]];
ret = rk[i];
}
}
for (i = l; i <= R[p]; i++) cnt[p+][q-][rk[i]]--;
for (i = L[q]; i <= r; i++) cnt[p+][q-][rk[i]]--;
return ret;
}
} int main()
{ scanf("%d%d",&n,&m);
for (i = ; i <= n; i++)
{
scanf("%d",&a[i]);
val[++len] = a[i];
}
sort(val+,val+len+);
len = unique(val+,val+len+) - val - ;
for (i = ; i <= n; i++) rk[i] = lower_bound(val+,val+len+,a[i]) - val;
block = (int)pow(n*1.0,1.0/);
if (block) t = n / block;
for (i = ; i <= block; i++)
{
L[i] = (i - ) * t + ;
R[i] = i * t;
}
if (R[block] < n)
{
block++;
L[block] = R[block-] + ;
R[block] = n;
}
for (i = ; i <= block; i++)
{
for (j = L[i]; j <= R[i]; j++)
{
pos[j] = i;
}
}
for (i = ; i <= block; i++)
{
for (j = i; j <= block; j++)
{
for (k = L[i]; k <= R[j]; k++)
cnt[i][j][rk[k]]++;
for (k = ; k <= len; k++)
{
if (cnt[i][j][k] > mx[i][j] || (cnt[i][j][k] == mx[i][j] && k < d[i][j]))
{
mx[i][j] = cnt[i][j][k];
d[i][j] = k;
}
}
}
}
lastans = ;
for (i = ; i <= m; i++)
{
scanf("%d%d",&l0,&r0);
l = (l0 + lastans - ) % n + ;
r = (r0 + lastans - ) % n + ;
if (l > r) swap(l,r);
printf("%d\n",lastans = val[query(l,r)]);
} return ; }

【BZOJ 2724】 蒲公英的更多相关文章

  1. bzoj 2724 蒲公英 分块

    分块,预处理出每两个块范围内的众数,然后在暴力枚举块外的进行比较 那么怎么知道每一个数出现的次数呢?离散后,对于每一个数,维护一个动态数组就好了 #include<cstdio> #inc ...

  2. BZOJ 2724 蒲公英 | 分块模板题

    题意 给出一个序列,在线询问区间众数.如果众数有多个,输出最小的那个. 题解 这是一道分块模板题. 一个询问的区间的众数,可能是中间"整块"区间的众数,也可能是左右两侧零散的数中的 ...

  3. BZOJ 2724蒲公英 (分块) 【内有块大小证明】

    题面 luogu传送门 分析 先分块,设块大小为x(之后我们会证明块大小取何值会更优) 步骤1 把所有的数离散化,然后对每个值开一个vector pos[i],pos[i]存储数i出现的位置 我们设查 ...

  4. [BZOJ 2724] [Violet 6] 蒲公英 【分块】

    题目链接:BZOJ - 2724 题目分析 这道题和 BZOJ-2821 作诗 那道题几乎是一样的,就是直接分块,每块大小 sqrt(n) ,然后将数字按照数值为第一关键字,位置为第二关键字排序,方便 ...

  5. BZOJ 2724: [Violet 6]蒲公英

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1633  Solved: 563[Submit][Status ...

  6. BZOJ 2724: [Violet 6]蒲公英( 分块 )

    虽然AC了但是时间惨不忍睹...不科学....怎么会那么慢呢... 无修改的区间众数..分块, 预处理出Mode[i][j]表示第i块到第j块的众数, sum[i][j]表示前i块j出现次数(前缀和, ...

  7. 【BZOJ 2724】 2724: [Violet 6]蒲公英 (区间众数不带修改版本)

    2724: [Violet 6]蒲公英 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 1908  Solved: 678 Description In ...

  8. 【刷题】BZOJ 2724 [Violet 6]蒲公英

    Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 Output Sample Input ...

  9. BZOJ 2724: [Violet 6]蒲公英 [分块 区间众数]

    传送门 题面太美不忍不放 分块分块 这种题的一个特点是只有查询,通常需要预处理:加入修改的话需要暴力重构预处理 预处理$f[i][j]$为第i块到第j块的众数,显然$f[i][j]=max{f[i][ ...

随机推荐

  1. Solr.NET快速入门(八)【多核多实例,映射验证】

    多核/多实例 本页介绍如何配置SolrNet访问(读/写)多个Solr内核或实例. 它假定您知道Solr内核是什么,如何在SolrNet外部配置和使用它们. 此页面不涵盖CoreAdminHandle ...

  2. WinForm和数据库的连接

    有几天没有写东西,今天来写点关于数据库的东西. 第一步:现在你自己的SQL Server数据库中创建一个新的数据库test,然后在里面新建一张表tb_user,在这张表中添加几个字段并为它赋值,具体结 ...

  3. Monad 系列

    本系列是在学习Monad时在网上找到的一个老外的博客,作者是MikeHadlow,地址是mikehadlow.blogspot.com,  可惜国内访问不了.这个系列对Monad讲解的浅显易懂,而且有 ...

  4. 4) 十分钟学会android--建立第一个APP,启动另一个Activity

    在完成上一课(建立简单的用户界面)后,我们已经拥有了显示一个activity(一个界面)的app(应用),该activity包含了一个文本字段和一个按钮.在这节课中,我们将添加一些新的代码到MyAct ...

  5. XML 之 命名空间详解

    最近学xml 遇到了点小问题qaq 找了n多的博客大佬,反复看了半小时终于明白了,可能我太蠢了... 基础的知识就不赘述,直接放“栗子”,切重点: <?xml version="1.0 ...

  6. caffe学习笔记--跑个SampleCode

    Caffe默认情况会安装在CAFFERROOT,就是解压到那个目录,例如: home/username/caffe-master, 所以下面的工作,默认已经切换到了该工作目录.下面的工作主要是,用于测 ...

  7. 几个方便编程的C++特性

    前言: C++11的自动化特性给编程提供了不少方便,同时也给调试增加了很多负担,至于取舍看程序员的风格和侧重而定. auto:自动类型推断 在C++11之前,auto关键字用来指定存储期.在新标准中, ...

  8. Nginx的安装与升级

    1,构建Nginx服务器; 2.升级版本; 一, 构建Nginx服务器 1.使用源码包安装nginx软件包 # yum -y install gcc pcre-devel openssl-devel  ...

  9. Docker镜像的备份和恢复

    备份: docker save -o [tar包真实路径] [镜像名 ] 如:docker save -o /usr/docker_data/mongo-backup.tar mongo   导出: ...

  10. JS 作业

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...