ABC355 D区间相交问题

ABC355 D区间相交问题

题意

给出n个区间,每个区间给出左端点(l)和右端点(r),判断有多少区间成对相交。

分析

如果我们直接暴力查找每个区间是否和别的区间相交,那么时间复杂度就是O(\(n^2\)),肯定是过不了的。

  • 考虑如何优化,通过题意,可以发现优化的关键在于区间相交的判定方式,对于任意两个区间l1,l2,r1,r2(l1<l2),考虑相交的情况就有三种判定方式,那么反过来想,判断不相交的情况就只有一种方式,即l2<r1,否则都会相交。然后就可以发现,判断不相交的方式简单,那么我们对全局就可以考虑假设全部相交再减去不相交的情况。
    • 全部相交,由于区间1与区间2相交等同与区间2与区间1相交。那么总相交次数为\(C_n^2\)=n(n-1)/2.
    • 不相交的次数的判断,对于任意rj,如果rj<li,那么就前面肯定有一个区间和(n-i+1)个区间不相交。
    • 从全局看,其实对于区间来说,每一个右端点必然大于左端点。这也是判断区间不相交的基础。那么对于相交的点来说,每个区间的匹配就不那么重要了,因为在相交的情况下,即使任意两个确定的左端点互换了右端点,对整体的相交并没有影响.由此可以推向全部区间。那么区间匹配不重要了,我们就可以直接排序左端点和右端点的数组。
  • 这样我们就可以利用双指针来遍历排序好的左端点,右端点数组。按照不相交的判断条件,从总和中减去就行了。
#include <bits/stdc++.h>
#define debug1(X) std::cout << #X << ": " << X << '\n'
#define debug2(X) std::cout << #X << ": " << X << ' '
using i64 = long long;
void solve()
{    
    i64 n;   
    std::cin>>n;  
     std::vector<int>l(n),r(n);  
    for(int i=0;i<n;i++){
        std::cin>>l[i]>>r[i];
    }
    std::sort(l.begin(),l.end());
    std::sort(r.begin(),r.end());
    i64 ans=n*(n-1)/2;
    int j=0;
    for(int i=0;i<n;i++){        
        while(j<n&&r[j]<l[i]){           
            j++;                      
            ans-=((n-i));          
        }        
    }
    std::cout<<ans<<"\n";
}
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    int t = 1;
    // std::cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}
posted @ 2024-05-27 11:27  拍手称快  阅读(11)  评论(0编辑  收藏  举报