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

  • 相关阅读:
    Linux Shell 下的输出重定向
    解决 Scrapy-Redis 空跑问题,链接跑完后自动关闭爬虫
    数据清洗基本概念
    前端常见的跨域请求解决方案
    Pandas模块:表计算与数据分析
    Matplotlib模块:绘图和可视化
    numpy如何使用
    Gerapy 使用详解
    MySQL常见数据库引擎及比较
    基于scrapy-redis组件的分布式爬虫
  • 原文地址:https://www.cnblogs.com/lcsdsg/p/14711581.html
Copyright © 2011-2022 走看看