CF474F Ant colony 线段树

版权声明:本文为DyingShu原创文章,转载请注明出处哦。 https://blog.csdn.net/DyingShu/article/details/82118110

传送门

又TM水了一道线段树…

题意:求区间GCD及等于这个GCD的数有多少个。输出区间长度-GCD数量
题解:
线段树维护区间GCD,再维护区间GCD数量。
显然当两个区间合并时,新区间的GCD等于左右区间GCD的GCD,而如果等于其中一个数,则数量就等于那个区间的GCD数量。
然后就完了。

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100001;

struct node{
    int gcd, tag;
    int l, r;
}t[MAXN << 2];

struct ANS{
    int tag, gcd;
}ans;

int a[MAXN];

inline int read(){
    int k = 0, f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
    return k * f;
}

int GCD(int a, int b){return b ? GCD(b, a % b) : a;}

inline void pushup(int u){
    t[u].gcd = GCD(t[u << 1].gcd, t[u << 1 | 1].gcd);
    if(t[u << 1].gcd == t[u << 1 | 1].gcd) t[u].tag = t[u << 1].tag + t[u << 1 | 1].tag;
    else if(t[u].gcd == t[u << 1].gcd) t[u].tag = t[u << 1].tag;
    else if(t[u].gcd == t[u << 1 | 1].gcd) t[u].tag = t[u << 1 | 1].tag;
    else t[u].tag = 0;
}

void build(int u, int L, int R){
    t[u].l = L, t[u].r = R;
    if(L == R){t[u].gcd = read(), t[u].tag = 1;return;}
    int mid = (L + R) >> 1;
    build(u << 1, L, mid), build(u << 1 | 1, mid + 1, R);
    pushup(u);
}

ANS query(int u, int L, int R){
//  printf("u = %d\n", u);
    ANS tmp;
    if(t[u].l >= L && t[u].r <= R){
        tmp.gcd = t[u].gcd;
        tmp.tag = t[u].tag;
        return tmp;
    }
    if(t[u << 1].r >= R) return query(u << 1, L, R);
    if(t[u << 1 | 1].l <= L) return query(u << 1 | 1, L, R);
    ANS s1 = query(u << 1, L, R), s2 = query(u << 1 | 1, L, R);
    tmp.gcd = GCD(s1.gcd, s2.gcd);
    if(s1.gcd == s2.gcd) tmp.tag = s1.tag + s2.tag;
    else if(tmp.gcd == s1.gcd) tmp.tag = s1.tag;
    else if(tmp.gcd == s2.gcd) tmp.tag = s2.tag;
    else tmp.tag = 0;
    return tmp;
}

int main(){
//  freopen("in.txt", "r", stdin);
    int n = read();
    build(1, 1, n);
    int m = read();
    while(m--){
        int l = read(), r = read();
        ans = query(1, l, r);
        printf("%d\n", r - l + 1 - ans.tag);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/DyingShu/article/details/82118110