zoukankan      html  css  js  c++  java
  • 二维偏序(逆序对,有序对)

    
    

    求逆序对问题:

    即例可以在数组{1,9,11,2,5,32,12}求有多少逆序对或者有序对。

    我们可以转化为二维坐标系。

    以数组的下标作为坐标的x轴,以数值作为坐标的y轴。

    如下图

    先按x轴排序,我们需要求在此点的左下方有多少点,即若现在为第k个点(xk,yk)那么求(1,k-1)之间有多少点x,y同时小于xk,yk,(此处我们求有序对),那么因为我们先按x轴排序了,所以我们只要求y轴比它小有几个就好了,这里我们用树状数组,从左到右遍历,每次求(1,yk-1)之间有几个数,然后对于(yk,max(y最大))进行区间加1更新就可以求出来了。

    顺序对代码

    #include<bits/stdc++.h> 
    using namespace std;
    const int MAXN=1000010;
    int maxValue,tr[MAXN];
    int lowbit(int x){
        return x&-x;
    }
    void add(int x,int k){
        for(int i=x;i<=maxValue;i+=lowbit(i)){
            tr[i]+=k;
        }
    }
    int sum(int l,int r){
        int ans=0;
        for(int i=r;i>0;i-=lowbit(i)){
            ans+=tr[i];
        }
        for(int i=l-1;i>0;i-=lowbit(i)){
            ans-=tr[i];
        }
        return ans;
    }
    struct Point{
        int a,b;
        bool operator <(const Point &another)const{
            return another.a<a;
        }//对于x轴方向上单调递增 
    };
    int pointCnt=0;
    int main(){
        int n;
        scanf("%d%d",&n,&maxValue);
        priority_queue<Point> q;
        for(int i=1;i<=n;i++){
            int tmpA,tmpB;
            scanf("%d%d",&tmpA,&tmpB);
            Point tmp=Point{tmpA,tmpB};
            q.push(tmp);
        }
        while(!q.empty()){
            Point nowPoint=q.top();q.pop();
            int nowValue=nowPoint.b;
            //cout<<nowValue<<endl; 
            cout<<sum(1,nowValue)<<endl;
            add(nowValue,1);//对于y轴大于nowvalue的加1 
        }
        return 0;
    }

  • 相关阅读:
    centos7.6 安装与配置 MongoDB yum方式
    MongoDB 介绍
    centos 关闭selinux
    前端 HTML标签属性
    前端 HTML 标签嵌套规则
    前端 HTML 标签分类
    前端 HTML body标签相关内容 常用标签 表单标签 form里面的 input标签介绍
    前端 HTML body标签相关内容 常用标签 表单标签 form 表单控件分类
    前端 HTML form表单标签 select标签 option 下拉框
    POJ 1426
  • 原文地址:https://www.cnblogs.com/lcsdsg/p/14711581.html
Copyright © 2011-2022 走看看