分析:(别人写的)

对于所有(l, r)区间,固定右区间,所有(li, r)一共最多只会有log个不同的gcd值,

可以nlogn预处理出所有不同的gcd区间,这样区间是nlogn个,然后对于询问离线处理,

用类似询问区间不同数字的方法,记录每个不同gcd最后出现的位置,然后用树状数组进行维护

注:我是看了这段文字会的,但是他的nlogn预处理我不会,我会nlog^2n的

dp[i][j]代表以i为右端点,向左延伸2^j个点(包括i)的gcd,然后因为这样的gcd满足递减,所以可以二分找区间

代码:

  1. /*RunID: 678021
  2. UserID: 96655
  3. Submit time: 2016-04-19 23:44:20
  4. Language: C++
  5. Length: 2378 Bytes.
  6. Result: Accepted
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <iostream>
  11. #include <algorithm>
  12. #include <string.h>
  13. using namespace std;
  14. typedef long long LL;
  15. const int INF=0x3f3f3f3f;
  16. const int N=1e4+;
  17. int T,n,m,dp[N][];
  18. struct ask{
  19. int l,r,id;
  20. bool operator<(const ask &rhs)const{
  21. return r<rhs.r;
  22. }
  23. }p[N*];
  24. struct Seg{
  25. int l,r,v;
  26. bool operator<(const Seg &rhs)const{
  27. return r<rhs.r;
  28. }
  29. }seg[*N];
  30. int erfen(int pos,int v){
  31. int l=,r=pos;
  32. while(l<r){
  33. int mid=(l+r)>>;
  34. int len=pos-mid+;
  35. int now=pos,cur=-;
  36. for(int i=;i>=;--i){
  37. if(len&(<<i)){
  38. if(cur==-)cur=dp[now][i];
  39. else cur=__gcd(cur,dp[now][i]);
  40. now-=(<<i);
  41. }
  42. }
  43. if(cur<v)l=mid+;
  44. else r=mid;
  45. }
  46. return (l+r)>>;
  47. }
  48. int hash[*N],tot,mat[*N];
  49. int res[N*];
  50. int c[N];
  51. void add(int x,int t){
  52. for(int i=x;i<=n;i+=i&(-i))
  53. c[i]+=t;
  54. }
  55. int get(int x){
  56. int ans=;
  57. if(x==)return ;
  58. for(int i=x;i>;i-=i&(-i))
  59. ans+=c[i];
  60. return ans;
  61. }
  62. int main(){
  63. scanf("%d",&T);
  64. while(T--){
  65. scanf("%d%d",&n,&m);
  66. for(int i=;i<=n;++i)
  67. scanf("%d",&dp[i][]);
  68. for(int i=;i<=m;++i)
  69. scanf("%d%d",&p[i].l,&p[i].r),p[i].id=i;
  70. for(int k=;(<<k)<=n;++k)
  71. for(int i=n;i>;--i){
  72. int j=i-(<<k)+;
  73. if(j<)break;
  74. j=i-(<<(k-));
  75. dp[i][k]=__gcd(dp[i][k-],dp[j][k-]);
  76. }
  77. int cnt=;tot=;
  78. for(int i=;i<=n;++i){
  79. int last=-;
  80. for(int j=i;j>;--j){
  81. int tmp=dp[j][];
  82. if(last!=-)tmp=__gcd(tmp,last);
  83. last=tmp;
  84. ++cnt;
  85. seg[cnt].l=j,seg[cnt].r=i,seg[cnt].v=last;
  86. hash[++tot]=last;
  87. j=erfen(i,last);
  88. }
  89. }
  90. sort(hash+,hash++tot);
  91. tot=unique(hash+,hash++tot)-hash-;
  92. sort(p+,p++m);
  93. sort(seg+,seg++cnt);
  94. memset(mat,,sizeof(mat));
  95. memset(c,,sizeof(c));
  96. int now=;
  97. for(int i=;i<=m;++i){
  98. for(;now<=cnt&&seg[now].r<=p[i].r;++now){
  99. int pos=lower_bound(hash+,hash++tot,seg[now].v)-hash;
  100. if(seg[now].l>mat[pos]){
  101. if(mat[pos])add(mat[pos],-);
  102. add(seg[now].l,);
  103. mat[pos]=seg[now].l;
  104. }
  105. }
  106. res[p[i].id]=get(p[i].r)-get(p[i].l-);
  107. }
  108. for(int i=;i<=m;++i)
  109. printf("%d\n",res[i]);
  110. }
  111. return ;
  112. }

FZU2224 An exciting GCD problem 区间gcd预处理+树状数组的更多相关文章

  1. 区间gcd问题 HDU 5869 离线+树状数组

    题目大意:长度n的序列, m个询问区间[L, R], 问区间内的所有子段的不同GCD值有多少种. 子段就是表示是要连续的a[] 思路:固定右端点,预处理出所有的gcd,每次都和i-1的gcd比较,然后 ...

  2. ACM学习历程—51NOD 1685 第K大区间2(二分 && 树状数组 && 中位数)

    http://www.51nod.com/contest/problem.html#!problemId=1685 这是这次BSG白山极客挑战赛的E题. 这题可以二分答案t. 关键在于,对于一个t,如 ...

  3. [BZOJ2225][SPOJ2371]LIS2 - Another Longest Increasing Subsequence Problem:CDQ分治+树状数组+DP

    分析 这回试了一下三级标题,不知道效果怎么样? 回到正题,二维最长上升子序列......嗯,我会树套树. 考虑\(CDQ\)分治,算法流程: 先递归进入左子区间. 将左,右子区间按\(x\)排序. 归 ...

  4. HDU 5869 Different GCD Subarray Query (GCD种类预处理+树状数组维护)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5869 问你l~r之间的连续序列的gcd种类. 首先固定右端点,预处理gcd不同尽量靠右的位置(此时gc ...

  5. 【HDU4947】GCD Array(莫比乌斯反演+树状数组)

    点此看题面 大致题意: 一个长度为\(n\)的数组,实现两种操作:将满足\(gcd(i,k)=d\)的\(a_i\)加上\(v\),询问\(\sum_{i=1}^xa_i\). 对于修改操作的推式子 ...

  6. A Simple Problem with Integers 多树状数组分割,区间修改,单点求职。 hdu 4267

    A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K ...

  7. poj_3468: A Simple Problem with Integers (树状数组区间更新)

    题目是对一个数组,支持两种操作 操作C:对下标从a到b的每个元素,值增加c: 操作Q:对求下标从a到b的元素值之和. 这道题也可以用线段树解,本文不做描述,下面分析如何用树状数组来解决这道题. 先把问 ...

  8. POJ 3468 A Simple Problem with Integers(树状数组区间更新)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 97217   ...

  9. poj 3468: A Simple Problem with Integers (树状数组区间更新)

    题目链接: http://poj.org/problem?id=3468 题目是对一个数组,支持两种操作 操作C:对下标从a到b的每个元素,值增加c: 操作Q:对求下标从a到b的元素值之和. 这道题也 ...

随机推荐

  1. 使用WebClient上传文件时的一些问题

    最近在使用WebClient做一个客户端上传图片到IIS虚拟目录的程序的时候,遇到了一些问题,这里主要给出参考步骤分享给大家. 测试环境 服务器端:Windows Server 2003,IIS6.0 ...

  2. React Native在虚拟运行app时,报错RCTRootView not found,怎么解决?

    报错: 解决方案:

  3. Python 守护进程

    import os import sys from time import sleep try: pid = os.fork() if pid > 0: sys.exit(0) # Exit p ...

  4. C# Windows Service调用IBM Lotus Notes发送邮件

    近日研究了下IBM Lotus Mail,这货果然是麻烦,由于公司策略,没有开放smtp,很多系统邮件都没有办法发送,于是入手google学习Lotus Mail,想做成Windows服务,提供wcf ...

  5. 软件测试 -- 和用户共同测试(UAT测试)的注意点有哪些

    软件产品在投产前,通常都会进行用户验收测试.如果用户验收测试没有通过,直接结果就是那不到“Money”,间接影响是损害了公司的形象,而后者的影响往往更严重.根据作者的经验,用户验收测试一定要让用户满意 ...

  6. Git权威指南 读笔(2)

    第七章 Git重置: Git提供了一个挽救机制,通过.git/logs目录下日志文件记录了分支的变更. master分支的日志文件.git/logs/refs/heads/master,显示最后5行: ...

  7. SWFUpload下载地址

    SWFUpload托管在谷歌代码上面,点击下载: https://code.google.com/p/swfupload/

  8. MongoDB索引介绍

    MongoDB中的索引其实类似于关系型数据库,都是为了提高查询和排序的效率的,并且实现原理也基本一致.由于集合中的键(字段)可以是普通数据类型,也可以是子文档.MongoDB可以在各种类型的键上创建索 ...

  9. Citect:How do I translate Citect error messages?

    http://www.opcsupport.com/link/portal/4164/4590/ArticleFolder/51/Citect   To decode the error messag ...

  10. 切换加上延迟加载js代码

    切换加上延迟加载js代码 (function(){ var tit = $("#tab02 li"), con = $("#wrapmp>div"), c ...