#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=;
int a[N],n,m,tmp;
struct tree{
int l,r,gcd,sum;
}tr[N*];
int gcd(int x,int y){
if(y==)return x;
else return gcd(y,x%y);
}
void update(int now){
int GCD=gcd(tr[now*].gcd,tr[now*+].gcd);
tr[now].gcd=GCD;
if(tr[now*].gcd==tr[now*+].gcd)tr[now].sum=tr[now*].sum+tr[now*+].sum;
else if(tr[now*].gcd==GCD)tr[now].sum=tr[now*].sum;
else if(tr[now*+].gcd==GCD)tr[now].sum=tr[now*+].sum;
else tr[now].sum=;
}
void build(int l,int r,int now){
tr[now].l=l;tr[now].r=r;
if(l==r){
tr[now].gcd=a[l];
tr[now].sum=;
return;
}
int mid=(l+r)>>;
build(l,mid,now*);
build(mid+,r,now*+);
update(now);
}
int getgcd(int l,int r,int now){
if(tr[now].l==l&&tr[now].r==r){
return tr[now].gcd;
}
int mid=(tr[now].l+tr[now].r)>>;
if(l>mid)return getgcd(l,r,now*+);
else if(r<=mid)return getgcd(l,r,now*);
else {
return gcd(getgcd(l,mid,now*),getgcd(mid+,r,now*+));
}
}
int check(int l,int r,int now){
if(tr[now].l==l&&tr[now].r==r){
if(tr[now].gcd==tmp)return tr[now].sum;
else return ;
}
int mid=(tr[now].l+tr[now].r)>>;
if(l>mid)return check(l,r,now*+);
else if(r<=mid)return check(l,r,now*);
else {
return check(l,mid,now*)+check(mid+,r,now*+);
}
}
int main(){
while(~scanf("%d",&n)){
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
}
build(,n,);
scanf("%d",&m);
for(int i=,l,r;i<=m;i++){
scanf("%d%d",&l,&r);
tmp=getgcd(l,r,);
printf("%d\n",r-l+-check(l,r,));
}
}
return ;
}

题意:

求区间gcd以及这个区间内的数字等于区间gcd的有多少个(其实是不等于,用区间长度减一下就好了)。

数据范围:1 ≤ n ≤ 105

题解

这题用线段树,但一眼望去这题似乎不满足合并,但实际上是可以的。

我们在线段树上维护两个东西,一个是区间gcd一个是区间中等于区间gcd的数的个数记为sum。

考虑如何合并,如果当前区间的两个字区间gcd相等,那么直接把sum相加就好,如果gcd等于两个gcd中的一个,那么sum就是相等gcd对应的那个,如果不相等,那么sum就为0。

为什么呢?gcd一定小于等于比区间所有数的最小值。gcd合并一定会减少或者不变,不变的话就是第一种情况,减少的话,gcd就比区间的所有数都小,所以区间中就不会有数等于gcd了。

最新文章

  1. 使用ajax获取JSON数据的jQuery代码的格式
  2. [Andrew]Ext.Net常用布局(Border布局)
  3. JS中的for和for in循环
  4. C#读取网页
  5. 《Android第一行代码》笔记
  6. hdu3294(manacher)
  7. SVN基于Maven的Web项目更新,本地过程详细解释
  8. 2016大连网络赛 Function
  9. Image和字节数组互转
  10. MATLAB垂直搜索图片中的白段
  11. vs2015 c# winfrom应用程序打包成64位
  12. cordova本地浮动框提示插件使用:cordova-plugin-x-toast
  13. Python编程Day7——字符编码、字符与字节、文件操作
  14. es6学习---.babelrc文件
  15. CentOS下KVM网卡设置成网桥时获取镜像端口的流量
  16. javascript显示年月日时间代码
  17. 【校招面试 之 C/C++】第5题 C++各种构造函数的写法
  18. android 的helloworld没跑起来 原因
  19. 20155213 2016-2017-2 《Java程序设计》第七周学习总结
  20. 需求:过滤下面这个网页里共723行 校对中里 行数为两位数的 行 并设置sz和rz在Windows和Linux之间发送和接收文件不用搭FTP

热门文章

  1. ZBrush中Local模式的旋转
  2. luogu P5290 [十二省联考2019]春节十二响 优先队列_启发式合并
  3. 8、Situation-Dependent Combination of Long-Term and Session-Based Preferences in Group Recommendations: An Experimental Analysis ----组推荐中基于长期和会话偏好的情景依赖组合
  4. 基础——(4)D Latch(D锁存器)
  5. node工具是是什么东西
  6. js 正则表达式 整合
  7. Codeforces 667B Coat of Anticubism
  8. 紫书 例题8-2 UVa 11605(构造法)
  9. navicat连接SQL Sever数据库出现的问题
  10. POJ 2230 Watchcow