【map乱搞】 HDU5126 GCD
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5726
题目大意:
给你n个数,m个询问。
每个询问给定
l
,
解题思路,先预处理把所有的GCD的结果搞出来,放到map里面去,最后询问的时候查询
[l,r]
的GCD,然后在map里面直接读取答案。
所以这个题目就是两部分咯。一部分是处理出结果,一部分是找到
[l,r]
的GCD。
后面一部分直接一个线段树解决。
前面一部分的话用map乱搞就好了。
具体的思路是这样的:
从右往左考虑。用map记录连续到
l+1
,的GCD的x的个数(代码中这个map是tmp)。
然后对于这个map的更新,无非就是从
l+1
到
l
<script type="math/tex" id="MathJax-Element-12">l</script>的更新。
那么遍历整个map,拿到所有的key,和a[l]算一下GCD然后更新一下就好了,就像DP一样。
大概的更新就是:
g=gcd(a[l],p->first);
tmp[g]+=p->second;
p->second-=p->second;
具体看代码。若有说错的地方,或有什么讲不清楚的地方。望指教。
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
#define MAXN 100000
#define lson root*2,l,mid
#define rson root*2+1,mid+1,r
const int MZ = 100000 + 10;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
//线段树求区间GCD用
struct QGCD {
int v[MZ * 4];
int cnt;
void build(int a[], int n) {
xx(1, 1, n, a);
}
void pushup(int rt) {
int le = rt << 1, ri = le | 1;
v[rt] = gcd(v[le], v[ri]);
}
void xx(int rt, int l, int r, int a[]) {
if (l == r)
v[rt] = a[l];
else {
int m = l + r >> 1;
int le = rt << 1, ri = le | 1;
xx(le, l, m, a);
xx(ri, m + 1, r, a);
pushup(rt);
}
}
int query(int root,int l,int r,int ll,int rr) {
if(ll<=l&&r<=rr) {
return v[root];
}
int ans=0;
int mid=l+r>>1;
if(mid>=ll)
{
ans=gcd(ans,query(lson,ll,rr));
}
if(mid<rr)
ans=gcd(ans,query(rson,ll,rr));
return ans;
}
};
QGCD sgt;
int a[MAXN+10];
int main()
{
int t;
scanf("%d",&t);
int ca=1;
while(t--) {
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",&a[i]);
sgt.build(a,n);
map<int,long long> tmp;
map<int,long long> ans;
for(int i=n; i>=1; i--) {
tmp[a[i]]+=1;
int pre=i;
for(map<int,long long>::iterator p=tmp.begin(); p!=tmp.end();) {
pair<int,long long> tt=*p;
int xx=gcd(a[i],tt.first);
ans[xx]+=tt.second;
tmp[xx]+=tt.second;
p->second-=tt.second;
if(p->second==0)
{
map<int,long long>::iterator q=p++;
tmp.erase(q);
}
else
p++;
}
}
int q;
scanf("%d",&q);
printf("Case #%d:\n",ca++);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
int qq=sgt.query(1,1,n,l,r);
printf("%d %I64d\n",qq,ans[qq]);
}
}
return 0;
}