ABC355 D区间相交问题
题意
给出n个区间,每个区间给出左端点(l)和右端点(r),判断有多少区间成对相交。
分析
如果我们直接暴力查找每个区间是否和别的区间相交,那么时间复杂度就是O(
- 考虑如何优化,通过题意,可以发现优化的关键在于区间相交的判定方式,对于任意两个区间l1,l2,r1,r2(l1<l2),考虑相交的情况就有三种判定方式,那么反过来想,判断不相交的情况就只有一种方式,即l2<r1,否则都会相交。然后就可以发现,判断不相交的方式简单,那么我们对全局就可以考虑假设全部相交再减去不相交的情况。
- 全部相交,由于区间1与区间2相交等同与区间2与区间1相交。那么总相交次数为
=n(n-1)/2. - 不相交的次数的判断,对于任意rj,如果rj<li,那么就前面肯定有一个区间和(n-i+1)个区间不相交。
- 从全局看,其实对于区间来说,每一个右端点必然大于左端点。这也是判断区间不相交的基础。那么对于相交的点来说,每个区间的匹配就不那么重要了,因为在相交的情况下,即使任意两个确定的左端点互换了右端点,对整体的相交并没有影响.由此可以推向全部区间。那么区间匹配不重要了,我们就可以直接排序左端点和右端点的数组。
- 全部相交,由于区间1与区间2相交等同与区间2与区间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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?