题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5869

Different GCD Subarray Query

Time Limit: 6000/3000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
#### 问题描述
> This is a simple problem. The teacher gives Bob a list of problems about GCD (Greatest Common Divisor). After studying some of them, Bob thinks that GCD is so interesting. One day, he comes up with a new problem about GCD. Easy as it looks, Bob cannot figure it out himself. Now he turns to you for help, and here is the problem:
>
> Given an array a of N positive integers a1,a2,⋯aN−1,aN; a subarray of a is defined as a continuous interval between a1 and aN. In other words, ai,ai+1,⋯,aj−1,aj is a subarray of a, for 1≤i≤j≤N. For a query in the form (L,R), tell the number of different GCDs contributed by all subarrays of the interval [L,R].

输入

There are several tests, process till the end of input.

For each test, the first line consists of two integers N and Q, denoting the length of the array and the number of queries, respectively. N positive integers are listed in the second line, followed by Q lines each containing two integers L,R for a query.

You can assume that

1≤N,Q≤100000

1≤ai≤1000000

输出

For each query, output the answer in one line.

样例输入

5 3

1 3 4 6 9

3 5

2 5

1 5

样例输出

6

6

6

题意

给你n个数排成一行,每次询问求一段区间内的所有子串的不同的gcd的种数有多少。

题解

首先,要处理出所有的子区间是比较困难的,而且事实上很多子区间的gcd都是重复出现的,我们把区间右端点固定,那么随着左区间从右往左移,区间gcd的值成倍递减,所以我们取到的不同的gcd的值只有logAi种,处理出来之后,我们就可以用离线的方式,用线段树来求区间不同的值有几个,每个事件(处理出来的sigma(logA[i])个区间gcd)以左端点为准插入树状数组中维护一下(离线查询的线段树/树状数组可以参考[这个])。

代码

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<stack>
#include<ctime>
#include<vector>
#include<cstdio>
#include<string>
#include<bitset>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
using namespace std;
#define X first
#define Y second
#define mkp make_pair
#define lson (o<<1)
#define rson ((o<<1)|1)
//#define mid (l+(r-l)/2)
#define sz() size()
#define pb(v) push_back(v)
#define all(o) (o).begin(),(o).end()
#define clr(a,v) memset(a,v,sizeof(a))
#define bug(a) cout<<#a<<" = "<<a<<endl
#define rep(i,a,b) for(int i=a;i<(b);i++)
#define scf scanf
#define prf printf typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
typedef vector<pair<int,int> > VPII; const int INF=0x3f3f3f3f;
const LL INFL=0x3f3f3f3f3f3f3f3fLL;
const double eps=1e-8;
const double PI = acos(-1.0); //start---------------------------------------------------------------------- const int maxn=1e5+10;
const int maxa=1e6+10; int gcd(int a,int b) {
return b==0?a:gcd(b,a%b);
} struct Node {
int l,r,v;
Node(int l,int r,int v):l(l),r(r),v(v) {}
}; bool cmp1(const Node& t1,const Node& t2) {
return t1.r<t2.r;
} int n,m;
int arr[maxn],ans[maxn];
int dp[maxn][20];
void rmq_init() {
for(int i=1; i<=n; i++) dp[i][0]=arr[i];
for(int j=1; (1<<j)<=n; j++) {
for(int i=1; i+(1<<j)-1<=n; i++) {
dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
}
} int query(int l,int r) {
int k=0;
while(l+(1<<k)-1<=r) k++;
k--;
return gcd(dp[l][k],dp[r-(1<<k)+1][k]);
} int sumv[maxn],mp[maxa]; void add(int x,int v) {
while(x<maxn) {
sumv[x]+=v;
x+=(-x)&x;
}
} int sum(int x) {
int ret=0;
while(x>0) {
ret+=sumv[x];
x-=x&(-x);
}
return ret;
} void init(){
clr(mp,0);
clr(sumv,0);
} int main() {
while(scf("%d%d",&n,&m)==2&&n) {
init();
for(int i=1; i<=n; i++) scanf("%d",&arr[i]);
rmq_init(); //v表示区间的gcd.
//处理出代表性的事件
vector<Node> events;
for(int i=1; i<=n; i++) {
int r=i;
while(r>0) {
int l=0,v=query(r,i);
events.pb(Node(r,i,v));
while(l+1<r) {
int mid=l+(r-l)/2;
int tmp=query(mid,i);
if(tmp==v) r=mid;
else l=mid;
}
r--;
}
} //v表示查询的id
vector<Node> que; for(int i=0; i<m; i++) {
int l,r;
scf("%d%d",&l,&r);
que.pb(Node(l,r,i));
} sort(all(que),cmp1);
sort(all(events),cmp1); //离线处理
int j=0;
rep(i,0,que.sz()) {
while(j<events.sz()&&events[j].r<=que[i].r){
Node& e=events[j];
if(mp[e.v]){
add(mp[e.v],-1);
}
add(e.l,1);
mp[e.v]=e.l;
j++;
}
ans[que[i].v]=sum(que[i].r)-sum(que[i].l-1);
} rep(i,0,m) prf("%d\n",ans[i]);
} return 0;
} //end-----------------------------------------------------------------------

HDU 5869 Different GCD Subarray Query rmq+离线+数状数组的更多相关文章

  1. HDU 5869 Different GCD Subarray Query 离线+树状数组

    Different GCD Subarray Query Problem Description   This is a simple problem. The teacher gives Bob a ...

  2. hdu 5869 Different GCD Subarray Query BIT+GCD 2016ICPC 大连网络赛

    Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K ( ...

  3. HDU 5869 Different GCD Subarray Query 树状数组+离线

    Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...

  4. HDU 5869 Different GCD Subarray Query 树状数组 + 一些数学背景

    http://acm.hdu.edu.cn/showproblem.php?pid=5869 题意:给定一个数组,然后给出若干个询问,询问[L, R]中,有多少个子数组的gcd是不同的. 就是[L, ...

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

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

  6. HDU 5869 Different GCD Subarray Query

    离线操作,树状数组,$RMQ$. 这个题的本质和$HDU$ $3333$是一样的,$HDU$ $3333$要求计算区间内不同的数字有几个. 这题稍微变了一下,相当于原来扫描到$i$的之后是更新$a[i ...

  7. HDU 5869 Different GCD Subarray Query(2016大连网络赛 B 树状数组+技巧)

    还是想不到,真的觉得难,思路太巧妙 题意:给你一串数和一些区间,对于每个区间求出区间内每段连续值的不同gcd个数(该区间任一点可做起点,此点及之后的点都可做终点) 首先我们可以知道每次添加一个值时gc ...

  8. 【刷题】HDU 5869 Different GCD Subarray Query

    Problem Description This is a simple problem. The teacher gives Bob a list of problems about GCD (Gr ...

  9. HDU 5869.Different GCD Subarray Query-区间gcd+树状数组 (神奇的标记右移操作) (2016年ICPC大连网络赛)

    树状数组... Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/6 ...

随机推荐

  1. CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令

    相关文章链接 CentOS6安装各种大数据软件 第一章:各个软件版本介绍 CentOS6安装各种大数据软件 第二章:Linux各个软件启动命令 CentOS6安装各种大数据软件 第三章:Linux基础 ...

  2. 使用Selenium慢慢向下滚动页面

    我正试图从航班搜索页面抓取一些数据. 此页面以这种方式工作: 你填写一个表格,然后你点击按钮搜索 – 这没关系.当您单击该按钮时,您将被重定向到包含结果的页面,这就是问题所在.这个页面连续添加结果,例 ...

  3. 树莓3B+_apt-get update && apt-get upgrade

    在Windows下安装软件,我们只需要有EXE文件,然后双击,下一步直接OK就可以了.但在LINUX下,不是这样的.每个LINUX的发行版,都会维护一个自己的软件仓库,我们常用的几乎所有软件都在这里面 ...

  4. 20155232 2016-2017-3 《Java程序设计》第10周学习总结

    20155232 2016-2017-3 <Java程序设计>第10周学习总结 教材学习内容总结 计算机网络 路由器和交换机组成了核心的计算机网络,计算机只是这个网络上的节点以及控制等,通 ...

  5. 20155233 《Java程序设计》 第十三周课堂练习总结

    20155233 <Java程序设计>第十三周课堂练习总结 测试题目 测试1 在IDEA中对P145 MathTool.java 使用JUnit进行单元测试,测试用例不少于三个,要包含正常 ...

  6. 20155307 2016-2017 《Java程序设计》第三次实验报告

    (一)敏捷开发与XP 敏捷开发是一种以人为核心.迭代.循序渐进的开发方法."敏捷流程"是一系列价值观和方法论的集合.从2001年开始,一些软件界的专家开始倡导"敏捷&qu ...

  7. 20155310 2016-2017-2 《Java程序设计》第九周学习总结

    20155310 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 JDBC入门 •数据库本身是个独立运行的应用程序 •撰写应用程序是利用通信协议对数据库进行指 ...

  8. mysql常用的命令

    一.事件操作: (1)查看事件启动状态 show variables like 'event_scheduler'; select @@event_scheduler; (2)启动事件 set glo ...

  9. day 11 大文件操作

    1.f.read(),  f.readline(),   f.readlines() ##### 1. f.read() 整体读 返回字符串 In [2]: f = open("aaa.py ...

  10. 【BZOJ4560】[NOI2016]优秀的拆分

    [BZOJ4560][NOI2016]优秀的拆分 题面 bzoj 洛谷 题解 考虑一个形如\(AABB\)的串是由两个形如\(AA\)的串拼起来的 那么我们设 \(f[i]\):以位置\(i\)为结尾 ...