【HDU5869】 Different GCD Subarray Query 题解 (线段树维护区间GCD)
题目大意:求区间$[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)的更多相关文章
- 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 ...
- CodeForces - 587E[线段树+线性基+差分] ->(线段树维护区间合并线性基)
题意:给你一个数组,有两种操作,一种区间xor一个值,一个是查询区间xor的结果的种类数 做法一:对于一个给定的区间,我们可以通过求解线性基的方式求出结果的种类数,而现在只不过将其放在线树上维护区间线 ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- 线段树维护区间前k小
线段树维护区间前k小 $ solution: $ 觉得超级钢琴太麻烦?在这里线段树提供一条龙服务 . 咳咳,开始讲正题!这道题我们有一个和超级钢琴复杂度一样 $ ~O(~\sum x\times lo ...
- FJUT3568 中二病也要敲代码(线段树维护区间连续最值)题解
题意:有一个环,有1~N编号,m次操作,将a位置的值改为b,问你这个环当前最小连续和多少(不能全取也不能不取) 思路:用线段树维护一个区间最值连续和.我们设出两个变量Lmin,Rmin,Mmin表示区 ...
- hdu_5726_GCD(线段树维护区间+预处理)
题目链接:hdu_5726_GCD 题意: 给你n个数(n<=1e5)然后m个询问(m<=1e5),每个询问一个区间,问你这个区间的GCD是多少,并且输出从1到n有多少个区间的GCD和这个 ...
- 51nod 1376【线段树维护区间最大值】
引自:wonter巨巨的博客 定义 dp[i] := 以数字 i(不是下标 i)为结尾的最长上升长度 然后用线段树维护 dp[i]: 每个节点维护 2 个信息,一个是当前区间的最大上升长度,一个是最大 ...
- 滑动窗口(poj,线段树维护区间最值)
题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...
- [CSP-S模拟测试]:椎(线段树维护区间最值和单调栈)
题目描述 虽不能至,心向往之. $Treap=Tree+Heap$ 椎$=$树$+$堆 小$\pi$学习了计算机科学中的数据结构$Treap$. 小$\pi$知道$Treap$指的是一种树. 小$\p ...
随机推荐
- 【js】栈方法和队列方法
栈方法:后进先出,推入(push)和弹出(pop):push("**")返回数组长度,pop()返回弹出的项. var colors = new Array(); // 创建一个数 ...
- scala 数据结构(七 ):集 Set
集是不重复元素的结合.集不保留顺序,默认是以哈希集实现 默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包 1 集 ...
- Mysql基础(七):数据库总结
目录 MySQL数据库06 /数据库总结 1. 数据库/DBMS 2. 数据库分类 3. 修改密码 4. 库操作 5. 表操作 6. 存储引擎 7. 事务 8. 约束 9. 数据类型 10. 单表语句 ...
- 前端06 /JavaScript之BOM、DOM
前端06 /JavaScript 目录 前端06 /JavaScript 昨日内容回顾 js的引入 js的编程要求 变量 输入输出 基础数据类型 number string boolean null ...
- xss小游戏源码分析
配置 下载地址:https://files.cnblogs.com/files/Lmg66/xssgame-master.zip 使用:下载解压,放到www目录下(phpstudy),http服务下都 ...
- Burp Suite Decoder Module - 解码模块
官方参考链接:https://portswigger.net/burp/documentation/desktop/tools/decoder 该模块主要进行编码和解码,支持编码方式有:Plain,U ...
- 【NET开发】图片处理类-仿照七牛云图片处理功能
介绍 Sop.Common.Img **请看 七牛云的图片处理功能介绍文档了解本项目功能 ** 此项目是有https://github.com/Sopcce/.Net-Common-Utility中的 ...
- LESS实战::not与:hover混合使用
举个例子,有个HTML是这样的. <div class="item light">A</div> <div class="item" ...
- 如何使用ABP进行软件开发(2) 领域驱动设计和三层架构的对比
简述 上一篇简述了ABP框架中的一些基础理论,包括ABP前后端项目的分层结构,以及后端项目中涉及到的知识点,例如DTO,应用服务层,整洁架构,领域对象(如实体,聚合,值对象)等. 笔者也曾经提到,AB ...
- 带你快速了解 MongoDB 分布式集群
在分布式应用系统中,mongodb 已经成为 NoSQL 经典数据库.要想很好的使用 mongodb,仅仅知道如何使用它是不够的.只有对其架构原理等有了充分认识,才能在实际运用中使其更好地服务于应用, ...