您的位置:首页 > 产品设计 > UI/UE

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

2016-09-12 22:28 459 查看


Different GCD Subarray Query

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 663 Accepted Submission(s): 230



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


Source

2016 ACM/ICPC Asia Regional Dalian Online

-----------------------------------------------------------------------------------------------------------------------------------------------------------

这片题解参考了这个网址:http://blog.csdn.net/miracle_ma/article/details/52504883。事实上本人是根据这篇博客才理解了这题的做法

题意:给一个序列,问这个序列[L,R]中的所有子序列中的数的公约数不同的个数。

思路:一个公约数要产生,肯定需要几个数通分才能得到,用一个树状数组来维护产生一个公约数的几个数在原数组中的最右位置。那么对于每个询问,知道其右端点R,就知道了[1,R]这个区间所有不同的公约数。然后我们再减去[1,L]中所有不同的公约数,就是[L,R]中不同的公约数。
枚举所有右端点,用map来记录公约数的出现位置,不断更新树状数组,用离线算法求得答案。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
typedef long long LL;
#define MS(x,y) memset(x,y,sizeof(x))
#define lowbit(x) (x&(-x))
const int MAXN=100000+5;
int a[MAXN];
LL ans[MAXN];
struct Query{
int l,r,id;
bool operator < (const Query& rhs) const{
return r<rhs.r||(r==rhs.r&&l<rhs.l);
}
}que[MAXN];
map<int,int> now[2],last;
map<int,int>:: iterator it;

LL tr[MAXN];
void add(int x,int v){
for(;x<MAXN;x+=lowbit(x)) tr[x]+=v;
}
LL query(int x){
LL ret=0;
for(;x;x-=lowbit(x)) ret+=tr[x];
return ret;
}

int main(){
int n,q;
while(~scanf("%d%d",&n,&q)){
MS(tr,0);
for(int i=1;i<=n;++i) scanf("%d",a+i);
for(int i=0;i<q;++i){
scanf("%d%d",&que[i].l,&que[i].r);
que[i].id=i;
}
sort(que,que+q);
now[0].clear();now[1].clear();
last.clear();
int x,tol=0,id1=0,id2=1;
MS(tr,0);
for(int i=1;i<=n;++i){
for(it=now[id1].begin();it!=now[id1].end();++it){
x=__gcd(a[i],it->first);
now[id2][x]=max(now[id2][x],it->second);
}
now[id2][a[i]]=i;
for(it=now[id2].begin();it!=now[id2].end();++it){
if(last.find(it->first)==last.end()) add(it->second,1);
else{
add(last[it->first],-1);
add(it->second,1);
}
last[it->first]=it->second;
}
now[id1].clear();
swap(id1,id2);
while(tol<q&&que[tol].r<=i){
ans[que[tol].id]=query(que[tol].r)-query(que[tol].l-1);
++tol;
}
}
for(int i=0;i<q;++i) printf("%I64d\n",ans[i]);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  stl 离线