CodeForces 272F - Ant colony线段树

题意:给出长度为n的串a,然后 给出q个询问 。对于每个询问 l,r,有一个计算其中对应的数的能量值的方法,比如power[l] 的计算方法就是 在区间[l,r]中能被 a[l]整除的数的个数。问这个区间中除去能量值等于r-l的个数还剩多少个。

因为个数 等于r-l  ,就相当于最小的数是 这个区间的最大公约数。就是求如果存在最小的数等于这个区间的最大公约数,最小的数的个数。

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <climits>

#include <string>

#include <iostream>

#include <map>

#include <cstdlib>

#include <list>

#include <set>

#include <queue>

#include <stack>

#include <math.h>

using namespace std;

typedef long long LL;

#define lson l,mid,rt<<1

#define rson mid+1,r,rt<<1|1

const int maxn = 111111;

const int INF = 1000000000 + 2;

int sum[maxn << 2], Min[maxn << 2], ret[maxn << 2];

int a[maxn];

int gcd(int a, int b)

{

    if (a%b == 0) return b;

    return gcd(b, a%b);

}

void up(int rt)

{

    Min[rt] = min(Min[rt << 1], Min[rt << 1 | 1]);

    sum[rt] = gcd(sum[rt << 1], sum[rt << 1 | 1]);

    if (Min[rt << 1] == Min[rt << 1 | 1]) ret[rt] = ret[rt << 1] + ret[rt << 1 | 1];

    if (Min[rt << 1] > Min[rt << 1 | 1]) ret[rt] = ret[rt << 1 | 1];

    if (Min[rt << 1] < Min[rt << 1 | 1]) ret[rt] = ret[rt << 1];

}



void build(int l, int r, int rt)

{

    if (l == r){

        Min[rt] = sum[rt] = a[l]; ret[rt] = 1;

        return;

    }

    int mid = (l + r) >> 1;

    build(lson);

    build(rson);

    up(rt);

}



int askmin(int L, int R, int l, int r, int rt)

{

    int ans = INF;

    if (L <= l&&r <= R) return Min[rt];

    int mid = (l + r) >> 1;

    if (L <= mid) ans = askmin(L, R, lson);

    if (R > mid) ans = min(ans, askmin(L, R, rson));

    return ans;

}



int askgcd(int L, int R, int l, int r, int rt)

{

    if (L <= l&&r <= R) return sum[rt];

    int ans1 = -1; int ans2 = -1;

    int mid = (l + r) >> 1;

    if (L <= mid) ans1 = askgcd(L, R, lson);

    if (R>mid) ans2 = askgcd(L, R, rson);

    if (ans1 == -1) return ans2;

    if (ans2 == -1) return ans1;

    return gcd(ans1, ans2);

}



int askret(int L, int R, int m, int l, int r, int rt)

{

    int ans = 0;

    if (L <= l&&r <= R){

        if (m == Min[rt]) return ret[rt];

        return 0;

    }

    int mid = (l + r) >> 1;

    if (L <= mid) ans += askret(L, R, m, lson);

    if (R>mid) ans += askret(L, R, m, rson);

    return ans;

}



int main()

{

    int n, l, r, q;

    cin >> n;

    for (int i = 1; i <= n; i++)

        scanf("%d", &a[i]);

    build(1, n, 1);

    cin >> q;

    for (int i = 0; i < q; i++){

        scanf("%d%d", &l, &r);

        int m = askmin(l, r, 1, n, 1);

        int Gcd = askgcd(l, r, 1, n, 1);

        if (Gcd == m)printf("%d\n", r - l + 1 - askret(l, r, m, 1, n, 1));

        else printf("%d\n", r - l + 1);

    }

    return 0;

}

 

你可能感兴趣的:(codeforces)