您的位置:首页 > 其它

Codeforces Round #271 (Div. 2) F - Ant colony 线段树 + GCD

2015-10-08 21:16 260 查看
Codeforces Round #271 (Div. 2) F - Ant colony

题意:

给定一个序列 有M个提问

每次提问求 给定区间中有多少个数 不能整除区间中其他的数 至少有一次.

思路:

题意转化一下就是求区间中有多少个数能整除其他数.
其实这个数就是区间的gcd 于是我们只要在求出区间中这个数的个数即可.
对于后者 学习到一个新方法 记录每次出现位置二分找.

#include <bits/stdc++.h>
#define lson num<<1
#define rson num<<1|1
#define gl l,m,lson
#define gr m+1,r,rson
#define PARA int l=1,int r=n,int num=1
using namespace std;
const int MAXN = 1e5+100;
int n;
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}

int a[MAXN];
struct Node
{
int st[MAXN<<2];
void pushUp(int num)
{
st[num]=gcd(st[lson],st[rson]);
}
void init(PARA)
{
int m=l+r>>1;
if(l!=r)
init(gl),init(gr),pushUp(num);
else
st[num]=a[l];
}
int query(int a,int b,PARA)
{
if(a<=l&&r<=b)
return st[num];
else
{
int m=l+r>>1;
if(b<=m)
return query(a,b,gl);
else if(a>m)
return query(a,b,gr);
else
return gcd(query(a,b,gl),query(a,b,gr));
}
}
}soul;

struct myPair
{
int a,b;
void init(int _a,int _b)
{
a=_a;
b=_b;
}
bool operator<(myPair o) const
{
return a==o.a?b<o.b:a<o.a;
}
}pr[MAXN],prt;

template <class T>
inline void scan_d(T &ret) {
char c; ret=0;
while((c=getchar())<'0'||c>'9');
while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();
}

int main()
{
scan_d(n);
for(int i=1;i<=n;i++)
scan_d(a[i]),pr[i].init(a[i],i);
sort(pr+1,pr+1+n);
soul.init();

int m,l,r,rl,rr,v;
scan_d(m);
while(m--)
{
scan_d(l);
scan_d(r);
v=soul.query(l,r);
prt.init(v,l);
rl=lower_bound(pr+1,pr+1+n,prt)-(pr+1);
prt.init(v,r+1);
rr=lower_bound(pr+1,pr+1+n,prt)-(pr+1);
printf("%d\n",r-l+1-(rr-rl));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: