Different GCD Subarray Query (离线的处理)
2016-09-11 15:37
351 查看
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].
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
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
题解:考虑固定左端点的不同GCD值,只有不超过logA种, 所以事件点只有nlogA个. 那么离线处理, 按照区间右端点排序从小到大处理询问,
用一个树状数组维护每个GCD值的最大左端点位置即可. 复杂度是O(nlogAlogn).
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include <vector>
#include <queue>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int T;
int n,m;
int a[120000];
int cnt=0;
struct Node
{
int num,id;
Node(){}
Node(int l,int id):num(l),id(id){}
} ;
vector<Node> L[120000];
vector<Node> que[120000];
int ans[120000];
int c[1200000];
int pp[1200000];
int N=1200000;
int lowbit(int x){return x&(-x);}
void add(int x,int val)
{
while(x<N)
{
c[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
if(x<0) return 0;
int re=0;
while(x)
{
re+=c[x];
x-=lowbit(x);
}
return re;
}
void init()
{
for(int i=1;i<=n;i++)
{
int x=a[i],y=i;
L[i].push_back(Node(x,y));
for(int j=0;j<L[i-1].size();j++)
{
int now = gcd(a[i],L[i-1][j].num),pos = L[i-1][j].id;
if(now!=x)
{
L[i].push_back(Node(now,pos));
x=now;
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
L[i].clear();
que[i].clear();
}
init();
memset(c,0,sizeof(c));
memset(pp,0,sizeof(pp));
int l,r;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
que[r].push_back(Node(l,i));
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<L[i].size();j++)
{
int num = L[i][j].num,pos = L[i][j].id;
if(pp[num]) add(pp[num],-1);
pp[num]=pos;
add(pp[num],1);
}
for(int j=0;j<que[i].size();j++)
{
int num = que[i][j].num,id = que[i][j].id;
ans[id] = sum(i) - sum(num-1);
}
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
return 0;
}
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].
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
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
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].
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
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
题解:考虑固定左端点的不同GCD值,只有不超过logA种, 所以事件点只有nlogA个. 那么离线处理, 按照区间右端点排序从小到大处理询问,
用一个树状数组维护每个GCD值的最大左端点位置即可. 复杂度是O(nlogAlogn).
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include <vector>
#include <queue>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f3f3f3f3f
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int T;
int n,m;
int a[120000];
int cnt=0;
struct Node
{
int num,id;
Node(){}
Node(int l,int id):num(l),id(id){}
} ;
vector<Node> L[120000];
vector<Node> que[120000];
int ans[120000];
int c[1200000];
int pp[1200000];
int N=1200000;
int lowbit(int x){return x&(-x);}
void add(int x,int val)
{
while(x<N)
{
c[x]+=val;
x+=lowbit(x);
}
}
int sum(int x)
{
if(x<0) return 0;
int re=0;
while(x)
{
re+=c[x];
x-=lowbit(x);
}
return re;
}
void init()
{
for(int i=1;i<=n;i++)
{
int x=a[i],y=i;
L[i].push_back(Node(x,y));
for(int j=0;j<L[i-1].size();j++)
{
int now = gcd(a[i],L[i-1][j].num),pos = L[i-1][j].id;
if(now!=x)
{
L[i].push_back(Node(now,pos));
x=now;
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
L[i].clear();
que[i].clear();
}
init();
memset(c,0,sizeof(c));
memset(pp,0,sizeof(pp));
int l,r;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&l,&r);
que[r].push_back(Node(l,i));
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<L[i].size();j++)
{
int num = L[i][j].num,pos = L[i][j].id;
if(pp[num]) add(pp[num],-1);
pp[num]=pos;
add(pp[num],1);
}
for(int j=0;j<que[i].size();j++)
{
int num = que[i][j].num,id = que[i][j].id;
ans[id] = sum(i) - sum(num-1);
}
}
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
}
return 0;
}
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].
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
Output
For each query, output the answer in one line.
Sample Input
5 3
1 3 4 6 9
3 5
2 5
1 5
Sample Output
6
6
6
相关文章推荐
- HDU 5869 Different GCD Subarray Query (离线处理 树状数组)
- HDU 5869 Different GCD Subarray Query(离线处理+树状数组)
- [区间GCD预处理 树状数组 离线] HDU 5869 Different GCD Subarray Query
- HDU 5869 Different GCD Subarray Query [区间gcd预处理+离线]【数据结构】
- Different GCD Subarray Query HDU - 5869 (gcd处理+离线线段树·)
- hdu 5869 Different GCD Subarray Query 预处理 + 离线
- [离线+树状数组] HDU5869 Different GCD Subarray Query
- HDU5869 Different GCD Subarray Query(离线线段树)
- HDU - 5869 Different GCD Subarray Query 树状数组离线处理
- HDU 5869 Different GCD Subarray Query(离线+gcd)
- hdu 5869 Different GCD Subarray Query 离线+树状数组
- hdu-5869 Different GCD Subarray Query gcd预处理 + 树状数组 + 离线
- HDU 5869 Different GCD Subarray Query (数学gcd+树状数组离线查询)
- HDU 5869 Different GCD Subarray Query 离线+树状数组
- [HDOJ5869] Different GCD Subarray Query(RMQ,树状数组,离线)
- HDU5869 Different GCD Subarray Query (离线+树状数组)
- HDU 5869 Different GCD Subarray Query 离线 树状数组
- 2016 大连网络赛 hdu 5869 Different GCD Subarray Query(gcd+树状数组)★ ★
- 2016 ICPC 大连网络赛 HDU 5869 Different GCD Subarray Query
- HDU5869 Different GCD Subarray Query(2016亚洲区大连站网络赛)