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

 

posted on 2014-10-13 13:08  一个西瓜  阅读(219)  评论(0编辑  收藏  举报

导航