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中的常用算法
- STL区间成员函数及区间算法总结
- c++ STL容器总结之:vertor与list的应用
- C++在成员函数中使用STL的find_if函数实例
- iOS开发之离线地图核心代码
- 关于STL中list容器的一些总结
- 最全面的百度地图JavaScript离线版开发
- 关于STL中的map容器的一些总结
- Android实现离线缓存的方法
- 浅析stl序列容器(map和set)的仿函数排序
- STL list链表的用法详细解析
- stl容器set,map,vector之erase用法与返回值详细解析
- STl中的排序算法详细解析
- 关于STL中vector容器的一些总结
- 关于STL中set容器的一些总结
- 简单说说STL的内存管理
- STL与泛型编程(1)---模板
- Android-WebView(五)优先加载本地资源(js, css等)
- Ambari在离线环境中安装Hadoop集群
- docker离线/内网/无外网安装