zoukankan      html  css  js  c++  java
  • 论"求最长重叠区间" 的两种方法

    论 "求最长重叠区间" 的两种方法

    问题描述

    给定n个区间,第i个区间表示为([L_i,R_i]),求出区间重叠长度的最大值 ;

    最大重叠长度 (Maxlength = max limits_{ 1leqslant j,k leqslant n , j eq k } { overlap( j , k ) }, overlap( j , k )) 表示 区间 j ,k的重叠部分的长度。

    解法一:双指针(尺取法)

    按区间左端点 L 的值对n个区间进行升序排序,对于区间 i ,向后依次遍历到区间 j ,

    (R_j>R_i) , 则区间 i 所能贡献的最大重叠长度,不可能超过 (R_i-L_j) ,可删除区间 i ,并跳转到 j(i = j),

    否则 区间 j 所能贡献的最大重叠长度,不可能超过(R_j-L_j) ,可删除区间 j ,继续向后遍历 (j = j+1);

    每次遍历到一个区间,都会有一个区间被删除,因此求解的时间复杂度是O((n)) ,加之排序的复杂度O((nlog_n)) ,总复杂度为O((nlog_n))。

    解法二:前缀最大值

    维护一个前缀最大值 (ma_i=max(ma_{i-1},R_i)) ,

    按区间左端点 L 的值对n个区间进行升序排序,根据贪心的思想,对于区间 i 查询 ,所有满足左端点 (lleqslant Li) 的区间,右端点 (r)的最大值 ,即 (ma_{i-1}); (因为排过序了,所以i 之前的所有区间都满足(leqslant L_i)) ,那么对于每一个区间 i ,我都通过前缀最大值向前O(1)查找了一个最大重叠长度 (length_i=min(ma_{i-1},Ri)-L_i) , (Maxlength=max limits_{1leqslant i leqslant n}length_i)

    我这里只是向前查找,却没有向后查找,是因为区间的相交是双向关系,若 (Maxlength = overlap(i,j) ,i<j) , 虽然 i 查询范围里没有j,但是j的查询范围却有i。

    这里的复杂度与解法一样,维护前缀最大值求解复杂度是O((n)) ,加之排序的复杂度O((nlog_n)) ,总复杂度为O((nlog_n))。

    值得一提的是,第一种解法是向后查找,因此重叠区间的左端点为(L_j) ,而第二种解法是向前查找,因此重叠区间的左端点为(L_i)

    代码

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef unsigned long long uLL;
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pLL;
    typedef pair<double,double> pdd;
    const int N=1e6+5;
    const int M=2e5+5;
    const int inf=0x3f3f3f3f;
    const LL mod=998244353;
    const double eps=1e-8;
    const long double pi=acos(-1.0L);
    #define ls (i<<1)
    #define rs (i<<1|1)
    #define fi first
    #define se second
    #define pb push_back
    #define eb emplace_back
    #define mk make_pair
    #define mem(a,b) memset(a,b,sizeof(a))
    LL read()
    {
        LL x=0,t=1;
        char ch;
        while(!isdigit(ch=getchar())) if(ch=='-') t=-1;
        while(isdigit(ch)){ x=10*x+ch-'0'; ch=getchar(); }
        return x*t;
    
    }
    pii a[N];
    int main()//solution 1
    {
        int n=read();
        for(int i=1;i<=n;i++) a[i].fi=read(),a[i].se=read();
        sort(a+1,a+n+1);
        int ans=0;
        for(int i=1;i<n;)
        {
            int j=i+1;
            while(j<=n)
            {
                ans=max(ans,min(a[i].se,a[j].se)-a[j].fi);
                if(a[j].se>a[i].se) break;
                j++;
            }
            i=j;
        }
        printf("%d
    ",ans);
        return 0;
    }
    /*
    solution 2
    int main()
    {
        int n=read();
        for(int i=1;i<=n;i++) a[i].fi=read(),a[i].se=read();
        sort(a+1,a+n+1);
        int ans=0,ma=0;
        for(int i=1;i<=n;i++)
        {
            ans=max(ans,min(a[i].se,ma)-a[i].fi);
            ma=max(ma,a[i].se);
        }
        printf("%d
    ",ans);
        return 0;
    }
    */
    
  • 相关阅读:
    [TCP IP详解:学习笔记]UDP:用户数据协议
    [TCP IP详解:学习笔记]IP选路
    [TCP IP详解:学习笔记]IP:网络协议
    [TCP IP详解:学习笔记]TCP连接的建立与终止
    [TCP IP详解:学习笔记]ICMP:Internet控制报文协议
    [TCP/IP详解:学习笔记]链路层
    [TCP/IP详解:学习笔记]ARP:地址解析协议
    [TCP IP详解:学习笔记]TCP:传输控制协议
    [TCP IP详解:学习笔记]广播和多播
    [TCP IP详解:学习笔记]IGMP:Internet组管理协议
  • 原文地址:https://www.cnblogs.com/DeepJay/p/14668575.html
Copyright © 2011-2022 走看看