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

Codeforces Round #271 (Div. 2) F - Ant colony

题意:

给定一个序列  有M个提问

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

思路:

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


#include 
#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
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;
}


你可能感兴趣的:(ACM,......数据结构,............线段树)