luogu4168蒲公英(区间众数)

给定n个数,m个区间询问,问每个询问中的众数是什么。

题面很漂亮,大家可以去看一下。

对于区间众数,由于区间的答案不能由子区间简单的找出来,所以似乎不能用树形结构。

用分块的话,设一个区间[x, y],里面包含的最大连续的块的左端点是l,右端点是r。那么显然,这个区间的众数要么是[l, r]的众数,要么是[x, l)和(r, y]中的任意数。所以可以用\(f[i][j]\)表示第i到j块的众数是什么,同时用\(s[i][x]\)表示前i个块中数x的出现次数。这样就可以做到\(n\sqrt{n}\)了。我的代码跑的算很快的。因为map没有sort快(废话)。

有一个很神的地方是f[i][j]只用保存一个值就行了,因为如果在第i个块到第j个块之间,还有数的出现次数和f[i][j]相同,那么它要超越f[i][j],必须满足在一侧的小区间中出现次数比f[i][j]多,所以它至少会在小区间中出现一次。

如果问题带修怎么办呢?还是可以用分块哟。由于我们要维护f[i][j]和s[i][j],只分\(n^{1/3}\)个块。对于某一个点上的修改,会牵动所有块。再维护cnt[i][j][k]表示i块到j块出现次数为k的数有几个即可。

#include <cmath>
#include <cctype>
#include <cstdio>
#include <algorithm>
using namespace std; const int maxn=4e4+5, sqrtm=2e2+5, INF=1e9;
int n, m, barlen, cntbar, a[maxn], bel[maxn], cnt[maxn];
int t[maxn], cntnum;
int s[sqrtm][maxn]; //前i个块x的出现次数
int f[sqrtm][sqrtm]; //第i到j块的众数是什么 void get(int &x){
x=0; char c; int flag=1;
for (c=getchar(); !isdigit(c); c=getchar());
for (x=c-48; c=getchar(), isdigit(c); )
x=x*10+c-48; x*=flag;
} int main(){
get(n); get(m); barlen=sqrt(n); cntbar=1;
for (int i=0; i<n; ++i){
get(a[i]); t[i]=a[i];
bel[i]=i/barlen;
if (i&&bel[i]!=bel[i-1]) ++cntbar;
}
sort(t, t+n); cntnum=unique(t, t+n)-t;
for (int i=0; i<n; ++i)
a[i]=lower_bound(t, t+cntnum, a[i])-t;
for (int i=0; i<n; ++i) ++s[bel[i]][a[i]];
for (int i=1; i<cntbar; ++i) //n^1.5
for (int j=0; j<n; ++j) s[i][j]+=s[i-1][j];
int maxm=0, mcnt, q1, q2, l, r, tmp;
for (int i=0; i<cntbar; ++i){ //n^1.5
for (int j=0; j<n; ++j) cnt[j]=0;
mcnt=0;
for (int j=i*barlen; j<n; ++j){
++cnt[a[j]];
if (cnt[a[j]]>mcnt||(cnt[a[j]]==mcnt&&a[j]<maxm))
mcnt=cnt[a[j]], maxm=a[j];
if (bel[j]!=bel[j+1]) f[i][bel[j]]=maxm;
}
}
maxm=0;
for (int iq=0; iq<m; ++iq){
get(q1); get(q2);
q1=(q1+maxm-1)%n; q2=(q2+maxm-1)%n; mcnt=0;
if (q1>q2) swap(q1, q2);
if (bel[q1]==bel[q2]){
maxm=INF;
for (int i=q1; i<=q2; ++i) cnt[a[i]]=0;
for (int i=q1; i<=q2; ++i){
++cnt[a[i]];
if (cnt[a[i]]>mcnt||(cnt[a[i]]==mcnt&&a[i]<maxm))
mcnt=cnt[a[i]], maxm=a[i];
}
printf("%d\n", maxm=t[maxm]);
continue;
}
l=bel[q1]+1; r=bel[q2]-1;
if (l<=r) maxm=f[l][r], mcnt=s[r][maxm]-s[l-1][maxm];
//cnt表示两边需要暴力查找的数的出现个数
for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i) cnt[a[i]]=0;
for (int i=q2; i==q2||bel[i]==bel[i+1]; --i) cnt[a[i]]=0;
for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i) ++cnt[a[i]];
for (int i=q2; i==q2||bel[i]==bel[i+1]; --i) ++cnt[a[i]];
for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i){
tmp=cnt[a[i]]+s[r][a[i]]-s[l-1][a[i]];
if (tmp>mcnt||(tmp==mcnt&&a[i]<maxm))
mcnt=tmp, maxm=a[i];
}
for (int i=q2; i==q2||bel[i]==bel[i+1]; --i){
tmp=cnt[a[i]]+s[r][a[i]]-s[l-1][a[i]];
if (tmp>mcnt||(tmp==mcnt&&a[i]<maxm))
mcnt=tmp, maxm=a[i];
}
printf("%d\n", maxm=t[maxm]);
}
return 0;
}

luogu4168蒲公英(区间众数)的更多相关文章

  1. P4168 [Violet]蒲公英 区间众数

    $ \color{#0066ff}{ 题目描述 }$ 在乡下的小路旁种着许多蒲公英,而我们的问题正是与这些蒲公英有关. 为了简化起见,我们把所有的蒲公英看成一个长度为n的序列 \((a_1,a_2.. ...

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

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

  3. 洛谷P4168 蒲公英 分块处理区间众数模板

    题面. 许久以前我还不怎么去机房的时候,一位大佬好像一直在做这道题,他称这道题目为"大分块". 其实这道题目的思想不只可以用于处理区间众数,还可以处理很多区间数值相关问题. 让我们 ...

  4. 蒲公英(bzoj2724)(分块+区间众数)

    Input Output Sample Input 6 3 1 2 3 2 1 2 1 5 3 6 1 5 Sample Output 1 2 1 HINT \(n <= 40000\),$ m ...

  5. Luogu4168 蒲公英 (分块)

    题目传送门 题意 长度为n的序列,有m次询问,每次询问求\([l,r]\) 间的众数,如果有多个,输出最小的那个 \(n\le 4\times 10^4,m\le 5\times 10^5,a_i\l ...

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

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

  7. bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式

    这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...

  8. 【luogu1468】[Violet]蒲公英--求区间众数

    题目背景 亲爱的哥哥: 你在那个城市里面过得好吗? 我在家里面最近很开心呢.昨天晚上奶奶给我讲了那个叫「绝望」的大坏蛋的故事的说!它把人们的房子和田地搞坏,还有好多小朋友也被它杀掉了.我觉得把那么可怕 ...

  9. 【BZOJ2724】蒲公英 题解(分块+区间众数)

    题目链接 题目大意:给定一段长度为$n$的序列和$m$次询问,每次询问区间$[l,r]$内的最小的众数.$n\leq 40000,a_i\leq 10^9$ --------------------- ...

随机推荐

  1. 序列化工具类({对实体Bean进行序列化操作.},{将字节数组反序列化为实体Bean.})

    package com.dsj.gdbd.utils.serialize; import java.io.ByteArrayInputStream; import java.io.ByteArrayO ...

  2. 分享知识-快乐自己:SpringBoot集成热部署配置(一)

    摘要: 热部署与热加载: ava热部署与Java热加载的联系和区别: 1):Java热部署与热加载的联系: 1.不重启服务器编译/部署项目 2.基于Java的类加载器实现 2):Java热部署与热加载 ...

  3. C++(八)— 死锁原因及解决方法

    1.死锁原因 死锁问题被认为是线程/进程间切换消耗系统性能的一种极端情况.在死锁时,线程/进程间相互等待资源,而又不释放自身的资源,导致无穷无尽的等待,其结果是任务永远无法执行完成. 打个比方,假设有 ...

  4. SpringBoot_异常_01_Caused by: java.lang.BootstrapMethodError: java.lang.NoSuchMethodError

    一.异常信息 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'gsonB ...

  5. Java微信开发_Exception_02_"errcode":40164,"errmsg":"invalid ip 61.172.68.219, not in whitelist hint

    ip查询网址: http://www.ip.cn/ 一.异常现象 今天开始做微信开发,在办公室时能正常获取access_token,晚上回家之后获取access_token时却报出下列错误信息: {& ...

  6. python生成excel格式座位表

    脚本分两个文件: 1.生成二维随机列表:GenerateLocaltion.py 2.将列表导入excel文件:CreateExcel.py 先上GenerateLocaltion.py: impor ...

  7. 关于MFC中重载函数是否调用基类相对应函数的问题

    在重载CDialog的OnInitDialog()函数的时候,在首行会添加一句:CDialongEx::OnInitDialog();语句,这是为什么呢?什么时候添加,什么时候不添加? 实际上,我们在 ...

  8. freeMarker(一)——freeMarker简介

    学习笔记,选自freeMarker中文文档,译自 Email: ddekany at users.sourceforge.net FreeMarker简介: FreeMarker 是一款 模板引擎: ...

  9. ACM学习历程—POJ 3764 The xor-longest Path(xor && 字典树 && 贪心)

    题目链接:http://poj.org/problem?id=3764 题目大意是在树上求一条路径,使得xor和最大. 由于是在树上,所以两个结点之间应有唯一路径. 而xor(u, v) = xor( ...

  10. bzoj 1312: Hard Life 01分数规划+网络流

    题目: Description 在一家公司中,人事部经理与业务部经理不和.一次,总经理要求人事部从公司的职员中挑选出一些来帮助业务部经理完成一项任务.人事部经理发现,在公司的所有职员中,有一些人相处得 ...