Problem Description
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] .
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] .
Input
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 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
Output
For each query, output the answer in one line.
Sample Input
复制代码
1
2
3
4
5
6
7
8
95 3 1 3 4 6 9 3 5 2 5 1 5
Sample Output
复制代码
1
2
3
4
5
6
76 6 6
Source
2016 ACM/ICPC Asia Regional Dalian Online
题意:给n个数,m个询问,每次问[l,r]区间内的所有子区间的GCD的不同值有多少个。
分析:区间不同值有一种离线的做法,考虑到以每个数为右端点的所有区间最多有log(n)个不同值,我们可以预处理出以每个数为右端点的不同gcd值,然后按照从左到右的顺序处理每个询问,当区间的右端固定时,我们用树状数组记下每种答案左端最晚出现的位置,这样对于每个询问直接用r结尾的总方案数减去(l-1)结尾的总方案数来得到答案。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92#include<iostream> #include<string> #include<algorithm> #include<cstdlib> #include<cstdio> #include<set> #include<map> #include<vector> #include<cstring> #include<stack> #include<cmath> #include<queue> #define INF 0x3f3f3f3f #define N 100005 using namespace std; typedef pair<int,int> pii; typedef long long ll; int n,q,ans[N],f[N],a[N],last[N*10]; vector<int> G[N]; int _gcd(int a,int b) { if(b == 0) return a; a %= b; return _gcd(b,a); } int lowbit(int x) { return x & (-x); } void Insert(int k,int x) { while(k <= n) { f[k] += x; k += lowbit(k); } } int Find(int k) { int ans = 0; while(k) { ans += f[k]; k -= lowbit(k); } return ans; } struct thing { int l,r; }ask[N]; int main() { while(~scanf("%d%d",&n,&q)) { memset(last,0,sizeof(last)); memset(f,0,sizeof(f)); for(int i = 1;i <= n;i++) { scanf("%d",&a[i]); G[i].clear(); } for(int i = 1;i <= q;i++) { scanf("%d%d",&ask[i].l,&ask[i].r); G[ask[i].r].push_back(i); } vector<pii> pre; for(int i = 1;i <= n;i++) { vector<pii> tmp; pre.push_back(make_pair(a[i],i)); for(pii v : pre) { if(tmp.size() && _gcd(v.first,a[i]) == tmp[tmp.size()-1].first) tmp[tmp.size()-1] = make_pair(_gcd(v.first,a[i]),v.second); else tmp.push_back(make_pair(_gcd(v.first,a[i]),v.second)); } for(pii v : tmp) { if(!last[v.first] || last[v.first] < v.second) { if(last[v.first]) Insert(last[v.first],-1); last[v.first] = v.second; Insert(last[v.first],1); } } pre = tmp; for(int v : G[i]) ans[v] = Find(ask[v].r) - Find(ask[v].l-1); } for(int i = 1;i <= q;i++) printf("%dn",ans[i]); } }
最后
以上就是明理狗最近收集整理的关于Hdu-5869 Different GCD Subarray Query(区间不同值离线算法)的全部内容,更多相关Hdu-5869内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复