题目大意:求区间$[L,R]$中所有子区间产生的最大公因数的个数。

-------------------------

对于$gcd$,我们知道$gcd(a,b,c)=gcd(gcd(a,b),c)$。所以我们可以利用$gcd$的传递性来求区间的$gcd$。如果$gcd$相同,那么保留下来位置相对靠右的那一个,这与我们查询的方式有关。我们在查询时是$O(n)$正向遍历的,询问的区间按照右端点进行关键字排序,每次维护一个新的$gcd$最靠右的位置并让这个位置+1,让之前的位置-1即可。

因为每次$gcd$结果至少除以2,所以复杂度降成了$\log$级别的。总复杂度$O(n\log n)$。

小细节:线段树建树的时候一定要从$0$开始建树,因为$pre[gcd]$是有可能等于$0$的。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=;
int a[maxn],n,T;
struct node
{
int p,g;
};
struct qq
{
int l,r,id;
}q[maxn];
struct t
{
int l,r,sum;
}tree[maxn<<];
vector<node> v[maxn];
int pre[*maxn];
int res[maxn];
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if (ch=='-') f=-;ch=getchar();}
while(isdigit(ch)){x=x*+ch-'';ch=getchar();}
return x*f;
}
int gcd(int a,int b)
{
if (!b) return a;
return gcd(b,a%b);
}
int cmp(qq a,qq b)
{
return a.r<b.r;
}
inline void build(int index,int l,int r)
{
tree[index].l=l;
tree[index].r=r;
if (l==r)
{
tree[index].sum=;
return;
}
int mid=(l+r)>>;
build(index*,l,mid);
build(index*+,mid+,r);
}
void change(int index,int pos,int x)
{
if (tree[index].l==tree[index].r)
{
tree[index].sum+=x;
return;
}
int mid=(tree[index].l+tree[index].r)>>;
if (mid>=pos) change(index*,pos,x);
else change(index*+,pos,x);
tree[index].sum=tree[index*+].sum+tree[index*].sum;
}
int query(int index,int l,int r)
{
if (l<=tree[index].l&&tree[index].r<=r)
{
return tree[index].sum;
}
int ans=,mid=(tree[index].l+tree[index].r)>>;
if (mid>=l) ans+=query(index*,l,r);
if (mid<r) ans+=query(index*+,l,r);
return ans;
}
signed main()
{
n=read(),T=read();
for (int i=;i<=n;i++) a[i]=read();
for (int i=;i<=T;i++) q[i].l=read(),q[i].r=read(),q[i].id=i;
build(,,n);
for (int i=;i<=n;i++)
{
int x=a[i],y=i,k=v[i-].size();
for (int j=;j<k;j++)
{
int u=v[i-][j].g;
int gg=gcd(u,x);
if (x!=gg)
{
v[i].push_back((node){y,x});
y=v[i-][j].p;
x=gg;
}
}
v[i].push_back((node){y,x});
}
sort(q+,q+T+,cmp);
int now=;
for (int i=;i<=n;i++)
{
int k=v[i].size();
for (int j=;j<k;j++)
{
int pp=v[i][j].p;
int gg=v[i][j].g;
change(,pre[gg],-);
pre[gg]=pp;
change(,pp,);
}
while (q[now].r==i)
{
int id=q[now].id;
res[id]=query(,q[now].l,q[now].r);
now++;
if (now>T) break;
}
}
//for (int i=1;i<=n<<2;i++) cout<<tree[i].sum<<endl;
for (int i=;i<=T;i++) printf("%lld\n",res[i]);
return ;
}

【HDU5869】 Different GCD Subarray Query 题解 (线段树维护区间GCD)的更多相关文章

  1. Can you answer these queries V SPOJ - GSS5 (分类讨论+线段树维护区间最大子段和)

    recursion有一个整数序列a[n].现在recursion有m次询问,每次她想知道Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 &l ...

  2. CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)

    题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...

  3. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  4. 线段树维护区间前k小

    线段树维护区间前k小 $ solution: $ 觉得超级钢琴太麻烦?在这里线段树提供一条龙服务 . 咳咳,开始讲正题!这道题我们有一个和超级钢琴复杂度一样 $ ~O(~\sum x\times lo ...

  5. FJUT3568 中二病也要敲代码(线段树维护区间连续最值)题解

    题意:有一个环,有1~N编号,m次操作,将a位置的值改为b,问你这个环当前最小连续和多少(不能全取也不能不取) 思路:用线段树维护一个区间最值连续和.我们设出两个变量Lmin,Rmin,Mmin表示区 ...

  6. hdu_5726_GCD(线段树维护区间+预处理)

    题目链接:hdu_5726_GCD 题意: 给你n个数(n<=1e5)然后m个询问(m<=1e5),每个询问一个区间,问你这个区间的GCD是多少,并且输出从1到n有多少个区间的GCD和这个 ...

  7. 51nod 1376【线段树维护区间最大值】

    引自:wonter巨巨的博客 定义 dp[i] := 以数字 i(不是下标 i)为结尾的最长上升长度 然后用线段树维护 dp[i]: 每个节点维护 2 个信息,一个是当前区间的最大上升长度,一个是最大 ...

  8. 滑动窗口(poj,线段树维护区间最值)

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

  9. [CSP-S模拟测试]:椎(线段树维护区间最值和单调栈)

    题目描述 虽不能至,心向往之. $Treap=Tree+Heap$ 椎$=$树$+$堆 小$\pi$学习了计算机科学中的数据结构$Treap$. 小$\pi$知道$Treap$指的是一种树. 小$\p ...

随机推荐

  1. Hadoop集群之浅析安全模式

    集群启动顺序: NameNode启动 NameNode启动时,首先将镜像文件(Fsimage)载入内存,并执行编辑日志(Edits)中的各项操作.一旦在内存中成功建立文件系统元数据的映像,则创建一个新 ...

  2. Qt_Demo3:实现棋盘

    1  简介 参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=53 说明:实现一个8*8的棋盘,点击棋盘的任意位置显示一个表情,并打印出当前的坐标( ...

  3. scrapy shell 的使用

    是什么?:是一个终端下的调试工具,用来调试scrapy 安装ipython :pip install ipython 启动: scrapy shell + 需要请求的url 进来之后,response ...

  4. 最大熵原理(The Maximum Entropy Principle)

    https://wanghuaishi.wordpress.com/2017/02/21/%E5%9B%BE%E8%A7%A3%E6%9C%80%E5%A4%A7%E7%86%B5%E5%8E%9F% ...

  5. Python面向对象04 /封装、多态、鸭子类型、类的约束、super

    Python面向对象04 /封装.多态.鸭子类型.类的约束.super 目录 Python面向对象04 /封装.多态.鸭子类型.类的约束.super 1. 封装 2. 多态 3. 鸭子类型 4. 类的 ...

  6. 从零搭建Spring Cloud Gateway网关(三)——报文结构转换

    背景 作为网关,有些时候可能报文的结构并不符合前端或者某些服务的需求,或者因为某些原因,其他服务修改报文结构特别麻烦.或者需要修改的地方特别多,这个时候就需要走网关单独转换一次. 实现 话不多说,直接 ...

  7. LeetCode 84 | 单调栈解决最大矩形问题

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第52篇文章,我们一起来看LeetCode第84题,Largest Rectangle in Histogram( ...

  8. 用maven打包java项目的pom文件配置

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  9. 什么?你正在学web自动化测试?那这些Selenium的基本操作你了解过吗?

    在自动化测试中,我们都知道是通过定位元素来实现的,那么有时候我们定位元素定位不到是为什么呢? 1.页面出现了iframe 2.出现了新的窗口,没有实现句柄的切换 3.三种等待方式,没有选择其中之一来使 ...

  10. CPU核数

    今天想看CPU核数,又忘记怎么看了QAQ. CPU的基本信息都被记录在/proc/cpuinfo中,一般直接cat /proc/cpuinfo就可以了. 主要是学习一下物理cpu核数/逻辑cpu核数的 ...