我好弱啊。。这题调了2天QwQ

  题目大意:给定一个长度为n(n<=40000)的序列,m(m<=50000)次询问l~r之间出现次数最多的数。(区间众数)

  这题如果用主席树就可以不用处理一堆前缀和。。蓝鹅我不会~T_T~

  把序列n分成sqrt(n)块,先把所有数离散化,预处理出poi[i][j]表示第i块到第j块的众数(即出现次数最多的数)。

  询问有两种情况:

  第一种情况是l~r在某个块中,那么直接扫一遍求出众数,效率O(sqrt(n))。

  第二种情况是l~r在多个块中,l在x块,r在y块,那么我们可以把它分为三部分:①l~x块最后一个数②x+1块~y-1块③y块第一个数~r。

  因为我们求出了poi数组,所以我们可以知道第二部分的众数,显然我们只要统计一下第一部分、第三部分每个数出现的次数,将它们和第二部分的众数出现的次数进行比较,出现次数最多的数就是l~r的众数。

  而第一部分、第三部分数的个数不超过2*sqrtn(n)个,所以扫一遍第一部分、第三部分的数,效率O(sqrt(n)),问题就是怎么O(1)求出第一部分、第三部分的每个数在l~r出现的次数了。如果是O(1),那么可以想到的就是前缀和,于是我们再预处理出qzh[i][a]表示前i块中a出现的次数,qzh2[i][j][a]表示第i块前j个数中a出现的次数。那么设第一部分某个数为a,l在x块,r在y块,它在l~r中出现的次数就是:

  qzh[y-1][a]-qzh[x-1][a]-qzh2[x][(l-1)%sqrtn==0?sqrtn:(l-1)%sqrtn][a]

  +qzh2[x][(r-1)%sqrtn+1==sqrtn?0:(r-1)%sqrtn+1][a]

  【写的好丑哇QAAAAQ

  第三部分同理,然后和第二部分预处理出来的众数在l~r出现的次数(求法同理)比较找出最大的就行了。

  预处理O(nsqrt(n)),询问O(qsqrt(n)),总的时间复杂度O((n+q)sqrt(n))。

代码如下:

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<algorithm>
  5. #include<cmath>
  6. #include<map>
  7. using namespace std;
  8. map<int,int>M[];
  9. struct zs{int num,pos;}b[];
  10. int n,m,l,r,cnt,ans,poi[][],a[],pos[],sum[],qzh[][],qzh2[][][],num[],ppos[][];
  11. bool v[];
  12. bool cmp(zs a,zs b){return a.num<b.num;}
  13. int main()
  14. {
  15. scanf("%d %d",&n,&m);
  16. int sqrtn=(int)ceil(sqrt(n));
  17. for(int i=;i<=n;i++)scanf("%d",&a[i]),b[i].num=a[i],b[i].pos=i;
  18. sort(b+,b++n,cmp);
  19. for(int i=;i<=n;i++)
  20. {
  21. if(b[i].num!=b[i-].num)cnt++;
  22. pos[b[i].pos]=cnt;
  23. }
  24. for(int i=;i<=sqrtn;i++)
  25. for(int j=;j<=sqrtn;j++)
  26. {
  27. if((i-)*sqrtn+j<=n)if(M[i].find(a[(i-)*sqrtn+j])==M[i].end())
  28. M[i][a[(i-)*sqrtn+j]]=++num[i];
  29. ppos[i][pos[(i-)*sqrtn+j]]=M[i][a[(i-)*sqrtn+j]];
  30. }
  31. for(int i=;i<=n;i++)qzh[((i-)/sqrtn)+][pos[i]]++;
  32. for(int i=;i<=n;i++)for(int j=;j<=sqrtn;j++)qzh[j][i]+=qzh[j-][i];
  33. for(int i=;i<=sqrtn;i++)for(int j=;j<=sqrtn;j++)if((i-)*sqrtn+j<=n)qzh2[i][j][ppos[i][pos[(i-)*sqrtn+j]]]++;
  34. for(int i=;i<=sqrtn;i++)
  35. {
  36. for(int k=;k<=sqrtn;k++)if((i-)*sqrtn+k<=n)v[pos[(i-)*sqrtn+k]]=;
  37. for(int k=;k<=sqrtn;k++)
  38. if((i-)*sqrtn+k<=n)
  39. if(!v[pos[(i-)*sqrtn+k]])
  40. {
  41. for(int j=;j<=sqrtn;j++)
  42. if((i-)*sqrtn+j<=n)qzh2[i][j][ppos[i][pos[(i-)*sqrtn+k]]]+=qzh2[i][j-][ppos[i][pos[(i-)*sqrtn+k]]];
  43. v[pos[(i-)*sqrtn+k]]=;
  44. }
  45. }
  46. for(int i=;i<=sqrtn;i++)
  47. {
  48. memset(sum,,sizeof(sum));
  49. int max=,maxi=;
  50. for(int j=i;j<=sqrtn;j++)
  51. {
  52. for(int k=;k<=sqrtn;k++)
  53. {
  54. int x=(j-)*sqrtn+k;
  55. if(x>n)break;
  56. if(++sum[pos[x]]>max||((sum[pos[x]]==max)&&(pos[x]<pos[maxi])))max=sum[pos[x]],maxi=x;
  57. }
  58. poi[i][j]=maxi;
  59. }
  60. }
  61. for(int i=;i<=m;i++)
  62. {
  63. scanf("%d %d",&l,&r);
  64. l=(l+ans-)%n+;r=(r+ans-)%n+;if(r<l)swap(l,r);
  65. if((int)ceil(r/sqrtn)==(int)ceil(l/sqrtn))
  66. {
  67. int maxx=,maxi=;
  68. memset(sum,,sizeof(sum));
  69. for(int j=l;j<=r;j++)
  70. if(++sum[pos[j]]>maxx||((sum[pos[j]]==maxx)&&(pos[j]<pos[maxi])))maxx=sum[pos[j]],maxi=j;
  71. ans=a[maxi];
  72. printf("%d\n",a[maxi]);
  73. }else
  74. {
  75. int ll=-,rr=;
  76. for(int j=;j<=sqrtn;j++)
  77. {
  78. if(j*sqrtn+>=l&&(ll==-))ll=j*sqrtn;
  79. if(j*sqrtn<=r)rr=j*sqrtn;
  80. }
  81. int y=poi[ll/sqrtn+][rr/sqrtn];
  82. for(int j=l;j<=ll;j++)
  83. {
  84. int lll=y;
  85. int x=qzh[rr/sqrtn][pos[j]]-qzh[max(ll/sqrtn-,)][pos[j]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[j]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[j]]];
  86. y=qzh[rr/sqrtn][pos[lll]]-qzh[max(ll/sqrtn-,)][pos[lll]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[lll]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[lll]]];
  87. if(x>y||((x==y)&&pos[j]<pos[lll]))y=j;else y=lll;
  88. }
  89. for(int j=rr+;j<=r;j++)
  90. {
  91. int lll=y;
  92. int x=qzh[rr/sqrtn][pos[j]]-qzh[max(ll/sqrtn-,)][pos[j]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[j]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[j]]];
  93. y=qzh[rr/sqrtn][pos[lll]]-qzh[max(ll/sqrtn-,)][pos[lll]]-qzh2[ll/sqrtn][(l-)%sqrtn==?sqrtn:(l-)%sqrtn][ppos[ll/sqrtn][pos[lll]]]+qzh2[rr/sqrtn+][(r-)%sqrtn+==sqrtn?:(r-)%sqrtn+][ppos[rr/sqrtn+][pos[lll]]];
  94. if(x>y||((x==y)&&pos[j]<pos[lll]))y=j;else y=lll;
  95. }
  96. printf("%d\n",a[y]);ans=a[y];
  97. }
  98. }
  99. }

bzoj2724: [Violet 6]蒲公英(离散化+分块)的更多相关文章

  1. bzoj2724: [Violet 6]蒲公英(分块)

    传送门 md调了一个晚上最后发现竟然是空间开小了……明明算出来够的…… 讲真其实我以前不太瞧得起分块,觉得这种基于暴力的数据结构一点美感都没有.然而今天做了这道分块的题才发现分块的暴力之美(如果我空间 ...

  2. [BZOJ2724][Violet 6]蒲公英

    [BZOJ2724][Violet 6]蒲公英 试题描述 输入 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1 输出 输入示 ...

  3. BZOJ_2724_[Violet 6]蒲公英_分块

    BZOJ_2724_[Violet 6]蒲公英_分块 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod ...

  4. BZOJ2724 [Violet 6]蒲公英 分块

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ2724.html 题目传送门 - BZOJ2724 题意 求区间最小众数,强制在线. $n$ 个数,$m ...

  5. 【分块】bzoj2724 [Violet 6]蒲公英

    分块,离散化,预处理出: ①前i块中x出现的次数(差分): ②第i块到第j块中的众数是谁,出现了多少次. 询问的时候,对于整块的部分直接获得答案:对于零散的部分,暴力统计每个数出现的次数,加上差分的结 ...

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

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

  7. BZOJ.2724.[Violet 6]蒲公英(静态分块)

    题目链接 区间众数 强制在线 考虑什么样的数会成为众数 如果一个区间S1的众数为x,那么S1与新区间S2的并的众数只会是x或S2中的数 所以我们可以分块先预处理f[i][j]表示第i到第j块的众数 对 ...

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

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

  9. 【BZOJ2724】[Violet 6]蒲公英 分块+二分

    [BZOJ2724][Violet 6]蒲公英 Description Input 修正一下 l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n ...

随机推荐

  1. 180710-MySql插入唯一键冲突的三种可选方式

    MySql插入时唯一键冲突的几种处理方式 MySql插入一条记录,结果提示主键冲突,怎么办? 批量插入数据时,发现插入的这批数据中,有某些记录存在唯一键冲突,一个一个跳出来就比较麻烦了,有什么好的办法 ...

  2. .net 使用com组件操作word遇到的一些问题

    1.警告: 方法“Microsoft.Office.Interop.Word._Document.Close(ref object, ref object, ref object)”和非方法“Micr ...

  3. 栈和队列ADT -数据结构(C语言实现)

    数据结构与算法分析 栈模型 限制插入和删除只能在表的末端的表 表的末端叫做栈顶(top) 支持Push进栈和Pop入栈操作 //LIFO后进先出表 栈的实现 链表实现 类型声明 struct Node ...

  4. SSH:远程登陆

    SSH用于计算机之间的加密登录的前提是公钥为真,所以存在中间人攻击中间人攻击:与https协议不同,SSH协议的公钥是没有CA公证的,当对公钥的请求被中间截获时,中间人可以发出伪造公钥干坏事而不被识破 ...

  5. 基于物品的协同过滤算法(ItemCF)

    最近在学习使用阿里云的推荐引擎时,在使用的过程中用到很多推荐算法,所以就研究了一下,这里主要介绍一种推荐算法—基于物品的协同过滤算法.ItemCF算法不是根据物品内容的属性计算物品之间的相似度,而是通 ...

  6. Linux 150命令之 文件和目录操作命令 cd pwd cp mv touch

    cd 切换目录 cd 目录 [root@mysql ~]# cd / [root@mysql /]# ls application bin class dev home lib64 media nfs ...

  7. HADOOP docker(十):hdfs 结构体系

    1.简介2.namenode和datanode3.The File System Namespace 文件系统命名空间4.Data Replication 数据复制5.Replica Placemen ...

  8. puppet学习笔记

    puppet优势:容易理解.用户较多.门槛低.简单.安装配置文件较少 puppet使用Ruby语言开发,安装puppet需要安装Ruby puppet运行环境:Redhat.Centos.Window ...

  9. Python中的相对导入语法

    Python中支持相对导入语法,即可以相对于某一个package进行导入,具体语法如下: # 导入"./dir2/spam.py", .表示当前目录 from .dir2 impo ...

  10. cp的使用

    一.形式 cp [options] source1 source2 source3 .... directory 参数意义: 参数 意义 -i 当目标文件已存在时,会询问是否覆盖 -p 连同文件的属性 ...