zoukankan      html  css  js  c++  java
  • CodeForces 474F Ant colony ST+二分

    Ant colony

    题解:

    因为一个数是合法数,那么询问区间内的其他数都要是这个数的倍数,也就是这个区间内的gcd刚好是这个数。

    对于这个区间的gcd来说,不能通过前后缀来算。

    所以通过ST表来询问这个区间的gcd。

    那么题目就变成了询问一个区间内有多少个k。

    我们对于每个数都离散化之后,在相应的数字存下下标。

    然后二分一下个数。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
    #define LL long long
    #define ULL unsigned LL
    #define fi first
    #define se second
    #define pb push_back
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define lch(x) tr[x].son[0]
    #define rch(x) tr[x].son[1]
    #define max3(a,b,c) max(a,max(b,c))
    #define min3(a,b,c) min(a,min(b,c))
    typedef pair<int,int> pll;
    const int inf = 0x3f3f3f3f;
    const int _inf = 0xc0c0c0c0;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const LL _INF = 0xc0c0c0c0c0c0c0c0;
    const LL mod =  (int)1e9+7;
    const int N = 1e5 + 100;
    int a[N], b[N];
    vector<int> vc[N];
    int m, n;
    int id(int x){
        int pos = lower_bound(b+1, b+1+m, x) - b;
        if(b[pos] == x) return pos;
        return -1;
    }
    int Log[N];
    struct ST {
        int dp[N][20], a[N];
        void init(int n) {
            for(int i = -(Log[0]=-1); i < N; i++)
                Log[i] = Log[i - 1] + ((i & (i - 1)) == 0);
            for(int i = 1; i <= n; ++i) dp[i][0] = a[i];
            for(int j = 1; j <= Log[n]; j++)
                for(int i = 1; i+(1<<j)-1 <= n; i++)
                    dp[i][j] = __gcd(dp[i][j-1], dp[i+(1<<(j-1))][j-1]);
        }
        int Query(int l, int r) {
            int k = Log[r - l + 1];
            return __gcd(dp[l][k], dp[r-(1<<k)+1][k]);
        }
    }st;
    int Ac(){
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i){
            scanf("%d", &a[i]);
            b[i] = a[i];
            st.a[i] = a[i];
        }
        st.init(n);
        sort(b+1, b+1+n);
        m = unique(b+1, b+1+n) - (b+1);
        for(int i = 1; i <= n; ++i){
            vc[id(a[i])].pb(i);
        }
        int q;
        scanf("%d", &q);
        int l, r;
        while(q--){
            scanf("%d%d", &l, &r);
            int x = st.Query(l, r);
            x = id(x);
            int ans = r - l + 1;
            if(~x){
                ans -= upper_bound(vc[x].begin(), vc[x].end(), r) - lower_bound(vc[x].begin(), vc[x].end(), l);
            }
            printf("%d
    ", ans);
        }
        return 0;
    }
    
    int main(){
        Ac();
        return 0;
    }
    View Code
  • 相关阅读:
    POJ 2240 Arbitrage spfa 判正环
    POJ 3259 Wormholes spfa 判负环
    POJ1680 Currency Exchange SPFA判正环
    HDU5649 DZY Loves Sorting 线段树
    HDU 5648 DZY Loves Math 暴力打表
    HDU5647 DZY Loves Connecting 树形DP
    CDOJ 1071 秋实大哥下棋 线段树
    HDU5046 Airport dancing links 重复覆盖+二分
    HDU 3335 Divisibility dancing links 重复覆盖
    FZU1686 神龙的难题 dancing links 重复覆盖
  • 原文地址:https://www.cnblogs.com/MingSD/p/10835068.html
Copyright © 2011-2022 走看看