题目

\(m\) 组询问求 \(\sum_{l\leq i,j\leq r}[a_i\bmod a_j==0],n,m,a_i\leq 5\times 10^5\)


分析

设 \(f(l,r,x)\) 表示 \(i 或 j\in [1,x],i或j\in [l,r]\) 时 的答案,\(g_x\) 表示 \([1,x]\) 的答案,根号的做法可以通过三秒

由于涉及区间内的求值,需要在莫队的基础上二次离线,那么从 \([l,r]\) 的答案扩展到 \([l,r']\) 就要加上 \(g(r')-g(r)-f(r+1,r',l-1)\)

从 \([l,r]\) 扩展到 \([l',r]\) 就要加上 \(f(l',l-1,r)-[g(l-1)-g(l'-1)]\),现在就是要求 f 和 g,后者可以通过前缀和实现

如果 \([l,r]\) 是作为因数,那么直接将 \(a_{1\sim x}\) 的因数统计个数,以 \(x\) 为第一关键字,即可做到 \(O(m\sqrt{n})\)

如果作为倍数,那么 \(a_{1\sim x}\) 中大于阈值的直接枚举倍数统计个数,小于等于的就要单独抽离出来,倘若现在枚举到 \(z\)

设 \(c_i\) 表示前 \(i\) 个数中 \(z\) 的倍数的个数,那么区间的答案就可以转化成前 \(x\) 个数中 \(z\) 的个数乘上 \(c_r-c_{l-1}\)

然后莫队的块长调到 \(1.5\sqrt{n}\),阈值调到 \(0.15\sqrt{\max\{a_i\}}\) 就可以过了,注意求 \(g_i\) 的时候要给每个位置减一,

因为 \((i,i)\) 和 \((i,i)\) 等价,但 \((i,j)\) 和 \((j,i)\) 在 \(a_i=a_j\) 时不等价


代码

  1. #include <cstdio>
  2. #include <cctype>
  3. #include <cmath>
  4. #include <algorithm>
  5. #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2?EOF:*p1++)
  6. using namespace std;
  7. const int N=500011; char buf[1<<21],puf[1<<21],*p1,*p2; int nowp=-1;
  8. struct rec{int l,r,rk;}q[N];
  9. struct node{int y,next;}e[N*27];
  10. struct Node{int x,y,rk,z,next;}E[N<<1];
  11. typedef long long lll; lll s[N],ans[N];
  12. int n,Q,bl,c[N],pos[N],a[N],b[N],as[N],bs[N],hs[N],rk[N],et,Et,m;
  13. int iut(){
  14. int ans=0; char c=getchar();
  15. while (!isdigit(c)) c=getchar();
  16. while (isdigit(c)) ans=ans*10+c-48,c=getchar();
  17. return ans;
  18. }
  19. void Flush(){fwrite(puf,1,nowp+1,stdout),nowp=-1;}
  20. void Putchar(char x){
  21. if (nowp==(1<<21)) Flush();
  22. puf[++nowp]=x;
  23. }
  24. void print(lll ans){
  25. char dig[21]; int len=-1;
  26. do{
  27. dig[++len]=ans%10+48,ans/=10;
  28. }while (ans);
  29. while (len>=0) Putchar(dig[len--]);
  30. }
  31. bool cmp(rec x,rec y){
  32. if (pos[x.l]!=pos[y.l]) return pos[x.l]<pos[y.l];
  33. return (pos[x.l]&1)?(x.r<y.r):(x.r>y.r);
  34. }
  35. int main(){
  36. n=iut(),Q=iut(),bl=sqrt(n)*1.5;
  37. for (int i=1;i<=n;++i) b[i]=a[i]=iut(),pos[i]=(i-1)/bl+1;
  38. for (int i=1;i<=Q;++i) q[i]=(rec){iut(),iut(),i};
  39. sort(q+1,q+1+Q,cmp);
  40. sort(b+1,b+1+n),m=unique(b+1,b+1+n)-b-1;
  41. bl=sqrt(m)*0.15+1;
  42. for (int i=1;i<=m;++i) rk[b[i]]=i;
  43. for (int i=1;i<=n;++i) a[i]=rk[a[i]];
  44. for (int i=1;i<=m;++i)
  45. for (int j=b[i];j<=b[m];j+=b[i])
  46. if (rk[j]){
  47. e[++et]=(node){rk[j],as[i]},as[i]=et;
  48. e[++et]=(node){i,bs[rk[j]]},bs[rk[j]]=et;
  49. }
  50. int L=q[1].l,R=q[1].l-1;
  51. for (int i=1;i<=Q;++i){
  52. if (L>q[i].l) E[++Et]=(Node){q[i].l,L-1,q[i].rk,1,hs[R]},hs[R]=Et,L=q[i].l;
  53. if (L<q[i].l) E[++Et]=(Node){L,q[i].l-1,q[i].rk,-1,hs[R]},hs[R]=Et,L=q[i].l;
  54. if (R>q[i].r) E[++Et]=(Node){q[i].r+1,R,q[i].rk,1,hs[L-1]},hs[L-1]=Et,R=q[i].r;
  55. if (R<q[i].r) E[++Et]=(Node){R+1,q[i].r,q[i].rk,-1,hs[L-1]},hs[L-1]=Et,R=q[i].r;
  56. }
  57. for (int i=1;i<=bl;++i){
  58. for (int j=1;j<=n;++j)
  59. if (b[a[j]]%b[i]==0) c[j]=c[j-1]+1;
  60. else c[j]=c[j-1];
  61. int now=0;
  62. for (int j=1;j<=n;++j){
  63. if (a[j]==i) ++now;
  64. if (b[a[j]]%b[i]==0) s[j]+=now;
  65. for (int k=hs[j];k;k=E[k].next)
  66. ans[E[k].rk]+=(c[E[k].y]-c[E[k].x-1])*now*E[k].z;
  67. }
  68. }
  69. for (int i=1;i<=n;++i) c[i]=0;
  70. for (int i=1;i<=n;++i){
  71. for (int j=bs[a[i]];j;j=e[j].next) ++c[e[j].y];
  72. if (a[i]>bl) for (int j=as[a[i]];j;j=e[j].next) ++c[e[j].y];
  73. s[i]+=c[a[i]]-1;
  74. for (int j=hs[i];j;j=E[j].next){
  75. int now=0;
  76. for (int k=E[j].x;k<=E[j].y;++k)
  77. now+=c[a[k]];
  78. ans[E[j].rk]+=now*E[j].z;
  79. }
  80. }
  81. for (int i=1;i<=n;++i) s[i]+=s[i-1];
  82. for (int i=1;i<=Et;++i) ans[E[i].rk]-=E[i].z*(s[E[i].y]-s[E[i].x-1]);
  83. for (int i=1;i<=Q;++i) ans[q[i].rk]+=ans[q[i-1].rk];
  84. for (int i=1;i<=Q;++i) print(ans[i]),Putchar(10);
  85. Flush();
  86. return 0;
  87. }

#莫队二次离线,根号分治#洛谷 5398 [Ynoi2018] GOSICK的更多相关文章

  1. 洛谷 P4887 -【模板】莫队二次离线(第十四分块(前体))(莫队二次离线)

    题面传送门 莫队二次离线 mol ban tea,大概是这道题让我第一次听说有这东西? 首先看到这类数数对的问题可以考虑莫队,记 \(S\) 为二进制下有 \(k\) 个 \(1\) 的数集,我们实时 ...

  2. luogu P4887 莫队二次离线

    珂朵莉给了你一个序列$a$,每次查询给一个区间$[l,r]$ 查询$l≤i<j≤r$,且$ai⊕aj$的二进制表示下有$k$个$1$的二元组$(i,j)$的个数.$⊕$是指按位异或. 直接暴力莫 ...

  3. luogu P4887 模板 莫队二次离线 莫队 离线

    LINK:模板莫队二次离线 很早以前学的知识点 不过 很久了忘了. 考虑暴力 :每次莫队更新的时候 尝试更新一个点到一个区间的答案 可以枚举二进制下位数为k的数字 看一下区间内的这种数字有多少个. 不 ...

  4. 洛谷P5398 [Ynoi2018]GOSICK(二次离线莫队)

    题面 传送门 题解 维包一生推 首先请确保您会二次离线莫队 那么我们现在的问题就是怎么转移了,对于\(i\)和前缀\([1,r]\)的贡献,我们拆成\(b_i\)和\(c_i\)两部分,其中\(b_i ...

  5. 【洛谷5398】[Ynoi2018]GOSICK(二次离线莫队)

    题目: 洛谷 5398 当我刚学莫队的时候,他们告诉我莫队能解决几乎所有区间问题: 现在,当我发现一个区间问题似乎难以用我所了解的莫队解决的时候,他们就把这题的正解叫做 XXX 莫队.--题记 (以上 ...

  6. BZOJ 4241: 历史研究——莫队 二叉堆

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4241 题意:N个int范围内的数,M次询问一个区间最大的(数字*出现次数)(加权众数),可以 ...

  7. 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

    2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...

  8. 浅谈分治 —— 洛谷P1228 地毯填补问题 题解

    如果想看原题网址的话请点击这里:地毯填补问题 原题: 题目描述 相传在一个古老的阿拉伯国家里,有一座宫殿.宫殿里有个四四方方的格子迷宫,国王选择驸马的方法非常特殊,也非常简单:公主就站在其中一个方格子 ...

  9. 洛谷P4117 [Ynoi2018]五彩斑斓的世界 [分块,并查集]

    洛谷 Codeforces 又是一道卡常题-- 思路 YNOI当然要分块啦. 分块之后怎么办? 零散块暴力,整块怎么办? 显然不能暴力改/查询所有的.考虑把相同值的用并查集连在一起,这样修改时就只需要 ...

  10. 【洛谷3674】小清新人渣的本愿(莫队,bitset)

    [洛谷3674]小清新人渣的本愿(莫队,bitset) 题面 洛谷,自己去看去,太长了 题解 很显然的莫队. 但是怎么查询那几个询问. 对于询问乘积,显然可以暴力枚举因数(反正加起来也是\(O(n\s ...

随机推荐

  1. Codeforces Round 927 (Div. 3)(A~F)

    目录 A B C D E F A 第一个遇到连续两个荆棘的地方就不能再赢金币了. 所以统计连续两个荆棘之前的所有金币 #include <bits/stdc++.h> #define in ...

  2. Linux cp命令直接覆盖不提示的方法

    今天在做项目的时候需要在linux上拷贝A项目中upload目录下所有的资源到B项目中的uoload目录下,所以我就打算使用[cp]命令拷贝过去,拷贝的时候我加了[-f]参数了,但还是一个个的询问我是 ...

  3. 获取一段时间内,以月/季度为单位,第N天在各个月/季度是几几年几月几号

    /** * 获取一段时间内(可跨年),以季度为单位,第N天在各个季度是几月几号 * @param $sTime 时间戳 * @param $eTime 时间戳 * @param $number 第N天 ...

  4. 树形dp套路

    我们知道dp也就是动态规划的思想就是先解决小问题,通过不断的解决小问题,最终解决大问题.那么能够应用树形dp套路的题目都应该符合一个条件,那就是通过解决每个子树的小问题,最终解决整棵树的大问题. 套路 ...

  5. Java实现书城项目(增删)

    书城项目 登录 dao 接口:UserDao Users login(String username,String password); 实现:UserDaoImpl QueryRunner quer ...

  6. 图片裁剪插件 vue-cropper [vue插件推荐]

    一个优雅的图片裁剪插件 https://www.npmjs.com/package/vue-cropper http://github.xyxiao.cn/vue-cropper/example/

  7. ida使用入门指北

    静态分析 快捷键 操作 作用 空格键 在反汇编窗口中,进行列表视图与图形视图之间的切换 TAB 在反汇编窗口中,进行汇编指令与伪代码之间的切换 Esc 和 Ctrl+Enter 翻页,返回前一页面 G ...

  8. 22_播放器之使用SDL显示YUV视频

    简介 使用SDL实现简单的YUV播放器. 这里还需要使用到像素格式和计算图片大小,这两个我们直接使用ffmpeg来实现,因此需要使用ffmpeg的libavutil/avutil.h和libavuti ...

  9. Linux环境下Minio的安装部署与启动教程(完整版)

    1.概述 MinIO是一个开源.分布式的对象存储系统,专为云原生环境设计.它提供了一个基于标准的Amazon S3兼容接口,使得开发者可以使用熟悉的API在私有云或边缘环境中部署和管理大规模非结构化数 ...

  10. 【732. 我的日程安排表 III】差分数组

    class MyCalendarThree { private TreeMap<Integer, Integer> cnt; public MyCalendarThree() { cnt ...