zoukankan      html  css  js  c++  java
  • 2019icpc徐州网络赛_I_query

    题意

    给定一个序列,多次询问区间([l,r])中满足(min(a[i],a[j])==gcd(a[i],a[j]))的数对((i,j))数。

    分析

    • 其实就是求区间有倍数关系的数对数。
    • 由于序列是全排列,所有有倍数关系的数对数只有(nlogn)个,因此可以暴力求出所有数对,然后对询问离线,转化为二位偏序的问题,使用树状数组解决即可。
    • 树状数组求逆序对其实就是求(i<j && a[i]>a[j])的二维偏序关系,而在这题里求的就是(l[i]<l[j] && r[i]>r[j])的二维偏序关系,其中(l[i],r[i])就是询问,所以将第一维排序,按树状数组求逆序数的方法计算即可。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e5+50;
    int n,m,l,r,c[N],a[N],p[N],ans[N];
    struct node{
        int o,id,l,r;
        bool operator<(const node& rhs)const{
            if(r==rhs.r){
                if(l==rhs.l){
                    //注意l和r都相同,询问点要放在后面...
                    return o<rhs.o;
                }else{
                    return l>rhs.l;
                }
            }else{
                return r<rhs.r;
            }
        }
    };
    vector<node> ns;
    int lowbit(int x){
        return x&(-x);
    }
    void add(int i,int x){
        while(i<=n){
            c[i]+=x;
            i+=lowbit(i);
        }
    }
    int sum(int i){
        int ans=0;
        while(i){
            ans+=c[i];
            i-=lowbit(i);
        }
        return ans;
    }
    int main(){
    //     freopen("in.txt","r",stdin);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            p[a[i]]=i;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+i;j<=n;j+=i){
                int a=p[i],b=p[j];
                if(a>b){
                    swap(a,b);
                }
                ns.push_back({1,0,a,b});
            }
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&l,&r);
            ns.push_back(node{2,i,l,r});
        }
        sort(ns.begin(),ns.end());
        int ad=0;
        int siz=ns.size();
        for(int i=0;i<siz;i++){
            if(ns[i].o==1){
                add(ns[i].l,1);
                ad++;
            }else{
                ans[ns[i].id]=ad-sum(ns[i].l-1);
            }
        }
        for(int i=1;i<=m;i++){
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    linux安装mongodb(设置非root用户和开机启动)
    Dubbo与Kubernetes集成
    利用Arthas定位线上问题实例
    利用JVM在线调试工具排查线上问题
    用Python写算法题--洛谷P1149 火柴棒等式
    通过实例理解Java网络IO模型
    Http协议Content-Length详解
    异步处理ServletRequest引发的血案
    漫谈递归和迭代
    ThinkPad笔记本外放没声音解决办法(不是驱动的原因)
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11496992.html
Copyright © 2011-2022 走看看