Description

转眼就要到Karin的生日了!Yuuna她们想为她准备生日礼物!现在有许多礼物被排列成了一个一维序列,每个礼物都有一个价值。Yuuna对这个序列十分感兴趣。因此,你需要多次回答:在某个区间内出现次数第k1少的价值是多少,可能多个不同的价值出现次数均为第k1少,输出其中第k2小的,保证输入合法。注意内存限制。
例如:对于一个区间而言(当然不一定是有序的):
1,2,3,4,5,5,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12
权值 出现次数
1 1 出现次数第1少 第1小
2 1 第2小
3 1 第3小
4 1 第4小
5 2 出现次数第2少 第1小
6 2 第2小
7 4 出现次数第3少 第1小
8 4 第2小
9 4 第3小
10 4 第4小
11 6 出现次数第4少 第1小
12 10 出现次数第5少 第1小
若k1=3,k2=2,代表询问这个区间里出现次数第3少的权值中第2小的,则应该输出8。
若k1=5,k2=1,代表询问这个区间里出现次数第5少的权值中第1小的,则应该输出12。
若k1=1,k2=3,代表询问这个区间里出现次数第1少的权值中第3小的,则应该输出3。

Input

第一行包括一个整数n,代表序列的长度。
第二行包括n个整数a1...an,代表该序列。
第三行包括一个整数m,代表询问的次数。
接下来m行,每行包括4个整数l,r,k1,k2,询问al...ar中出现次数第k1少的权值中第k2小的。

Output

对于每个询问,仅输出一行,包括一个整数,代表你的回答。

很显然可以用莫队算法,关键在于维护状态转移。权值分块可以做到O(1)插入/删除,O(√(n))查询第k大,可以用于维护每种出现次数有几个权值以及相同出现次数的不同权值。由均摊分析可知,每种出现次数的权值数之和为n,于是可以预处理离散化并给每个出现次数的权值分块分配对应的空间。可以做到O(n)预处理,O(m√(n))查询,O(n)空间,但常数较大。

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cmath>
  4. int _(){
  5. int x=,c=getchar();
  6. while(c<)c=getchar();
  7. while(c>)x=x*+c-,c=getchar();
  8. return x;
  9. }
  10. int n,m,v[],B,id[],ts[],ans[],t1[],t2[],mt[],mc[];
  11. int*l0[],*r0[],*l1[],*l2[],*l3[],_mem[],*mp=_mem;
  12. struct Q{
  13. int l,r,k1,k2,ID;
  14. void init(int i){
  15. l=_();r=_();k1=_();k2=_();ID=i;
  16. }
  17. bool operator<(const Q&w)const{
  18. return id[l]!=id[w.l]?id[l]<id[w.l]:r!=w.r?(r<w.r)!=(id[l]&):ID<w.ID;
  19. }
  20. }q[];
  21. void insv(int x,int y){
  22. if(!t1[x]++)++t2[x/B];
  23. y=l3[y][x];
  24. ++l1[x][y];
  25. ++l2[x][y/B];
  26. }
  27. void delv(int x,int y){
  28. if(!--t1[x])--t2[x/B];
  29. y=l3[y][x];
  30. --l1[x][y];
  31. --l2[x][y/B];
  32. }
  33. void ins(int x){
  34. if(ts[x]>)delv(ts[x],x);
  35. ++ts[x];
  36. if(ts[x]>)insv(ts[x],x);
  37. }
  38. void del(int x){
  39. if(ts[x]>)delv(ts[x],x);
  40. --ts[x];
  41. if(ts[x]>)insv(ts[x],x);
  42. }
  43. int rnk(int x,int k){
  44. for(int i=,s=;;++i){
  45. if(s+l2[x][i]>=k){
  46. for(int j=i*B;;++j)if((s+=l1[x][j])==k)return l0[x][j];
  47. }
  48. s+=l2[x][i];
  49. }
  50. }
  51. int main(){
  52. n=_();
  53. B=sqrt(n+)+;
  54. for(int i=;i<=n;++i)++mc[++mt[v[i]=_()]],id[i]=(i-)/B;
  55. for(int i=;i<=n;++i){
  56. l0[i]=r0[i]=mp;mp+=mc[i];
  57. l1[i]=mp;mp+=mc[i];
  58. l2[i]=mp;mp+=mc[i];
  59. l3[i]=mp-;mp+=mt[i];
  60. }
  61. for(int i=;i<=n;++i)for(int j=;j<=mt[i];++j)l3[i][j]=r0[j]-l0[j],*r0[j]++=i;
  62. m=_();
  63. for(int i=;i<m;++i)q[i].init(i);
  64. std::sort(q,q+m);
  65. int L=,R=;
  66. for(int i=;i<m;++i){
  67. int l=q[i].l,r=q[i].r;
  68. while(L>l)ins(v[--L]);
  69. while(L<l)del(v[L++]);
  70. while(R<r)ins(v[++R]);
  71. while(R>r)del(v[R--]);
  72. for(int j=,s=;;++j){
  73. if(s+t2[j]>=q[i].k1){
  74. int k=B*j;
  75. while(s<q[i].k1)if(t1[k++])++s;--k;
  76. ans[q[i].ID]=rnk(k,q[i].k2);
  77. break;
  78. }
  79. s+=t2[j];
  80. }
  81. }
  82. for(int i=;i<m;++i)printf("%d\n",ans[i]);
  83. return ;
  84. }

bzoj 3920: Yuuna的礼物的更多相关文章

  1. BZOJ.3920.Yuuna的礼物(莫队 分块套分块 分段离散化)

    题目链接 详细题解:https://www.cnblogs.com/autsky-jadek/p/4376091.html 代码参考自:https://www.cnblogs.com/Sakits/p ...

  2. bzoj3920: Yuuna的礼物(莫队+分块套分块)

    思路挺简单的,但是总感觉好难写...码力还是差劲,最后写出来也挺丑的 这题显然是个莫队题,考虑怎么转移和询问... 根据莫队修改多查询少的特点,一般用修改快查询慢的分块来维护.查第$k_1$小的出现次 ...

  3. 【莫队算法】【权值分块】bzoj3920 Yuuna的礼物

    [算法一] 暴力. 可以通过第0.1号测试点. 预计得分:20分. [算法二] 经典问题:区间众数,数据范围也不是很大,因此我们可以: ①分块,离散化,预处理出: <1>前i块中x出现的次 ...

  4. [BZOJ3920]Yuuna的礼物

    题目大意: 给你一个长度为$n(n\le40000)$的数列$\{a_i\}(1\le a_i\le n)$,给出$m(m\le40000)$次询问,每次给出$l,r,k_1,k_2$询问区间$[l, ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. bzoj 3055礼物运送 floyed + 状压DP

    bzoj 3055: 礼物运送 floyed first 设f[i][S]表示取到了S集合中的所有点(不一定是经过的所有点),最后停在了i的最优值. 初始就f[i][{i}] = dis[1][i] ...

  7. bzoj 4827 礼物

    bzoj 4827 礼物 可以看做将其中一个数列(假定为 \(a\) )都加上 \(c\) , \(c\) 可以为负数.易知这里 \(-m\leq c\leq m\). 记要求的答案为 \(ans\) ...

  8. BZOJ 3438 小M的礼物

    BZOJ 3438 小M的礼物 Description 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子 有1个(就是可以种一棵作物)(用1. ...

  9. bzoj 4827: [Hnoi2017]礼物 [fft]

    4827: [Hnoi2017]礼物 题意:略 以前做的了 化一化式子就是一个卷积和一些常数项 我记着确定调整值还要求一下导... #include <iostream> #include ...

随机推荐

  1. java中byte数据转换为c#的byte数据

    最近在做下载方面的开发.有一个需求,就是读取要下载的文件中的一些数据,比如要读取这个文件包含的用户信息,但是怎么读都不对.后来搞了很久才发现,服务器上的文件里的用户信息,用C#写的存储方法来存储的,而 ...

  2. (实用篇)PHPExcel读取Excel文件的实现代码

    用PHPExcel读取Excel 2007 或者Excel2003文件,需要的朋友,可以参考下. 涉及知识点:  php对excel文件进行循环读取 php对字符进行ascii编码转化,将字符转为十进 ...

  3. NetSetMan IP地址切换工具

    http://www.netsetman.com/en/freeware NetSetMan NetSetMan是一个网络设置管理器,它可以很容易在6种不同的,视觉结构化的配置之间切换,包括: IP地 ...

  4. meta标签兼容性

    基本标签SEO 优化为移动设备添加 viewportWindows 8其他 禁止数字识自动别为电话号码不让android识别邮箱每 8 秒刷新一次页面移动端的头部标签和meta 基本标签 声明文档使用 ...

  5. ZOJ 1005 Jugs

    原题链接 题目大意:有一大一小两个杯子,相互倒水,直到其中一个杯子里剩下特定体积的水.描述这个过程. 解法:因为两个杯子的容积互质,所以只要用小杯子不断往大杯子倒水,大杯子灌满后就清空,大杯子里迟早会 ...

  6. sqlserver函数

    SQLServer时间日期函数详解,SQLServer,时间日期, 1.      当前系统日期.时间 select getdate() 2. dateadd      在向指定日期加上一段时间的基础 ...

  7. php--部分session与cookie

    Cookie 是什么? cookie 常用于识别用户.cookie 是一种服务器留在用户计算机上的小文件.每当同一台计算机通过浏览器请求页面时,这台计算机将会发送 cookie. 特点:1.没有过期时 ...

  8. js部分---流程语句的基本形式;

    while  do-while  for  for-in   return break  continue   if  swich   try-catch异常语句处理

  9. JavaWeb学习记录(九)——Cookie的增加、删除、查看

    一.servlet功能代码: public void doGet(HttpServletRequest request, HttpServletResponse response)           ...

  10. Sublime Text3快捷方式与使用技巧

    Sublime Text 3 快捷键精华版 Ctrl+Shift+P:  打开命令面板Ctrl+P:  搜索项目中的文件Ctrl+G: 跳转到第几行Ctrl+W: 关闭当前打开文件Ctrl+Shift ...