• [CF474F] Ant colony


    Description

    给定一个长度为 (n) 的序列,有 (q) 组询问,每次询问给定一个下标区间 ([l,r]),问这个区间中,有多少数可以整除区间中的所有数。

    Solution

    对于区间 ([l,r])(a_i) 整除所有数即 (a_i | extrm{gcd}(a_l,a_{l+1},...,a_r))

    (g= extrm{gcd}(a_l,a_{l+1},...,a_r)),可以用线段树在 (O(log n)) 时间内求出

    (a_i | g and a_i le g Rightarrow a_i = g),于是只需要统计区间中等于 (g) 的个数即可

    对所有数字离散化后,对每种数用 vector 存储其出现位置,查询时在 vector 上二分即可

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 1000005;
    const int dbg = 0;
    
    int n,q,t1,t2,t3,l,r;
    int a[N];
    
    int gcd(int x,int y)
    {
        return __gcd(x,y);
    }
    
    namespace seg
    {
    int a[N];
    
    void build(int p,int l,int r,int *src)
    {
        if(l==r)
        {
            a[p]=src[l];
        }
        else
        {
            build(p*2,l,(l+r)/2,src);
            build(p*2+1,(l+r)/2+1,r,src);
            a[p]=gcd(a[p*2],a[p*2+1]);
        }
    }
    
    int query(int p,int l,int r,int ql,int qr)
    {
        if(l>qr || r<ql) return 0;
        if(l>=ql && r<=qr) return a[p];
        return gcd(query(p*2,l,(l+r)/2,ql,qr), query(p*2+1,(l+r)/2+1,r,ql,qr));
    }
    }
    
    namespace cnter
    {
    map <int,int> mp;
    int imp[N];
    int ind=0;
    vector <int> vec[N];
    
    void init()
    {
        for(int i=1;i<=n;i++) mp[a[i]]++;
        for(auto &i:mp) i.second=++ind, imp[ind]=i.first;
        for(int i=1;i<=n;i++) vec[mp[a[i]]].push_back(i);
    }
    
    int query(int l,int r,int key)
    {
        int pos=mp[key];
        if(pos)
        {
            vector <int> &v = vec[pos];
            auto it1=lower_bound(v.begin(),v.end(),l);
            auto it2=lower_bound(v.begin(),v.end(),r+1);
            return it2-it1;
        }
        else return 0;
    }
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
    
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
        seg::build(1,1,n,a);
        cnter::init();
        cin>>q;
        for(int i=1;i<=q;i++)
        {
            cin>>l>>r;
            int g=seg::query(1,1,n,l,r);
            if(dbg) cout<<" g = "<<g<<endl;
            int ans=cnter::query(l,r,g);
            cout<<r-l+1-ans<<endl;
        }
    }
    
    
  • 相关阅读:
    [转]oracle数据库定时任务dbms_job的用法详解
    身份证号码的正则表达式及验证详解(JavaScript,Regex)
    js数组操作
    jq滚动到底部加载更多方法
    jq之实现轮播
    node之npm一直出错
    Jq之21点游戏
    移动端屏幕适配viewport
    meta属性
    用户体验之表单结构
  • 原文地址:https://www.cnblogs.com/mollnn/p/13584666.html
Copyright © 2020-2023  润新知