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的数有几个即可。

  1. #include <cmath>
  2. #include <cctype>
  3. #include <cstdio>
  4. #include <algorithm>
  5. using namespace std;
  6. const int maxn=4e4+5, sqrtm=2e2+5, INF=1e9;
  7. int n, m, barlen, cntbar, a[maxn], bel[maxn], cnt[maxn];
  8. int t[maxn], cntnum;
  9. int s[sqrtm][maxn]; //前i个块x的出现次数
  10. int f[sqrtm][sqrtm]; //第i到j块的众数是什么
  11. void get(int &x){
  12. x=0; char c; int flag=1;
  13. for (c=getchar(); !isdigit(c); c=getchar());
  14. for (x=c-48; c=getchar(), isdigit(c); )
  15. x=x*10+c-48; x*=flag;
  16. }
  17. int main(){
  18. get(n); get(m); barlen=sqrt(n); cntbar=1;
  19. for (int i=0; i<n; ++i){
  20. get(a[i]); t[i]=a[i];
  21. bel[i]=i/barlen;
  22. if (i&&bel[i]!=bel[i-1]) ++cntbar;
  23. }
  24. sort(t, t+n); cntnum=unique(t, t+n)-t;
  25. for (int i=0; i<n; ++i)
  26. a[i]=lower_bound(t, t+cntnum, a[i])-t;
  27. for (int i=0; i<n; ++i) ++s[bel[i]][a[i]];
  28. for (int i=1; i<cntbar; ++i) //n^1.5
  29. for (int j=0; j<n; ++j) s[i][j]+=s[i-1][j];
  30. int maxm=0, mcnt, q1, q2, l, r, tmp;
  31. for (int i=0; i<cntbar; ++i){ //n^1.5
  32. for (int j=0; j<n; ++j) cnt[j]=0;
  33. mcnt=0;
  34. for (int j=i*barlen; j<n; ++j){
  35. ++cnt[a[j]];
  36. if (cnt[a[j]]>mcnt||(cnt[a[j]]==mcnt&&a[j]<maxm))
  37. mcnt=cnt[a[j]], maxm=a[j];
  38. if (bel[j]!=bel[j+1]) f[i][bel[j]]=maxm;
  39. }
  40. }
  41. maxm=0;
  42. for (int iq=0; iq<m; ++iq){
  43. get(q1); get(q2);
  44. q1=(q1+maxm-1)%n; q2=(q2+maxm-1)%n; mcnt=0;
  45. if (q1>q2) swap(q1, q2);
  46. if (bel[q1]==bel[q2]){
  47. maxm=INF;
  48. for (int i=q1; i<=q2; ++i) cnt[a[i]]=0;
  49. for (int i=q1; i<=q2; ++i){
  50. ++cnt[a[i]];
  51. if (cnt[a[i]]>mcnt||(cnt[a[i]]==mcnt&&a[i]<maxm))
  52. mcnt=cnt[a[i]], maxm=a[i];
  53. }
  54. printf("%d\n", maxm=t[maxm]);
  55. continue;
  56. }
  57. l=bel[q1]+1; r=bel[q2]-1;
  58. if (l<=r) maxm=f[l][r], mcnt=s[r][maxm]-s[l-1][maxm];
  59. //cnt表示两边需要暴力查找的数的出现个数
  60. for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i) cnt[a[i]]=0;
  61. for (int i=q2; i==q2||bel[i]==bel[i+1]; --i) cnt[a[i]]=0;
  62. for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i) ++cnt[a[i]];
  63. for (int i=q2; i==q2||bel[i]==bel[i+1]; --i) ++cnt[a[i]];
  64. for (int i=q1; i==q1||bel[i]==bel[i-1]; ++i){
  65. tmp=cnt[a[i]]+s[r][a[i]]-s[l-1][a[i]];
  66. if (tmp>mcnt||(tmp==mcnt&&a[i]<maxm))
  67. mcnt=tmp, maxm=a[i];
  68. }
  69. for (int i=q2; i==q2||bel[i]==bel[i+1]; --i){
  70. tmp=cnt[a[i]]+s[r][a[i]]-s[l-1][a[i]];
  71. if (tmp>mcnt||(tmp==mcnt&&a[i]<maxm))
  72. mcnt=tmp, maxm=a[i];
  73. }
  74. printf("%d\n", maxm=t[maxm]);
  75. }
  76. return 0;
  77. }

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. Delphi操作XML - 冰雪傲骨

    Delphi操作XMl,只要使用 NativeXml.我是用的版本是4..NativeXML的使用方法比较简单,但是功能很强大. XE2的话,要在simdesign.inc后面加上: // Delph ...

  2. IDT 数据预览查询

    前面做了一件非常愚蠢的事情,由于不会预览数据.我都是直接发布到webi去查看的.可以想象一下了.真是太年轻了.为自己感到十分的汗颜. 在数据基础层做好连接之后,可以查看数据基础 .会显示相应的join ...

  3. Tomcat_异常_03_Tomcat日志(Logger)中文乱码

    一.异常现象 tomcat的日志中出现中文乱码 二.异常解决 2.1 修改catalina.sh文件 在 Tomcat安装目录下的bin目录中,修改catalina.sh文件,第229行. (1)修改 ...

  4. Maven 将jar导入本地maven仓库

    目录 环境变量配置maven 执行一下命令即可 诚邀访问我的个人博客:我在马路边 更好的阅读体验点击查看原文:Maven将jar倒入本地maven仓库 原创博客,转载请注明出处 @ 在Java项目开发 ...

  5. 桥接以及Mercury MW54R中继

    家里连个路由器,一个是比较先进的TP-Link的TL-WR842N(100M),另外一个是比较古老的水星(Mercury) MW54R(54M),我们知道新的路由器都有WDS功能,方便作为副路由器(中 ...

  6. BZOJ1217:[HNOI2003]消防局的设立

    我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

  7. 洛谷 4178 Tree——点分治

    题目:https://www.luogu.org/problemnew/show/P4178 点分治.如果把每次的 dis 和 K-dis 都离散化,用树状数组找,是O(n*logn*logn),会T ...

  8. POJ 1046 Color Me Less(浅水)

    一.Description A color reduction is a mapping from a set of discrete colors to a smaller one. The sol ...

  9. 使用cmd命令行方式登录ftp上传下载数据

    部分用户在使用ftp工具登录空间上传下载过程中经常会遇到各种问题,如主动模式,被动模式,以及其他导致无法登陆ftp .上传数据.下载数据的问题,这时候不妨使用一下命令行方式.命令行下可以避免很多由于f ...

  10. flume 配置与使用

    1.下载flume,解压到自建文件夹 2.修改flume-env.sh文件 在文件中添加JAVA_HOME 3.修改flume.conf 文件(原名好像不叫这个,我自己把模板名改了) 里面我自己配的( ...