Description
Input
Output
Sample Input
3
10 100
1 50
50 100
Sample Output
99
Data Constraint
Solution
首先把每个区间按左端点从小到大排一遍序。
当做到第 i 个区间,其左右端点分别为
l,r ,考虑在前面 i−1 个区间中找一个(其左右端点设为 l′,r′ ,显然有 l′<l )与它匹配。
考虑区间相交和区间包含这两种情况:
当区间相交时:答案即为 (l−l′)+(r−r′)=l+r−(l′+r′) ,则应使 l′+r′ 最小。
当区间包含时:答案即为 (l−l′)+(r′−r)=r′−l′−(r−l) ,则应使 r−l 最大。
那么这样运用贪心的思想,用两个堆维护两种情况的最值即可。
注意当堆顶的区间的右端点比当前区间的左端点小的话( r′<l ),
说明两区间不相交,且以后也不会再相交( l 递增),弹出堆即可。
时间复杂度
O(N log N) 。
Code
#pragma GCC optimize(2)
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N=200001;
struct data
{
int x,y;
data(int xx,int yy){x=xx,y=yy;}
bool operator <(const data &z)const
{
return x>z.x;
}
};
pair<int,int>a[N];
priority_queue<data>q1,q2;
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
int main()
{
freopen("test.in","r",stdin);
int n=read(),ans=0;
for(int i=1;i<=n;i++) a[i].first=read(),a[i].second=read();
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
int l=a[i].first,r=a[i].second;
while(!q1.empty() && q1.top().y<l) q1.pop();
while(!q2.empty() && q2.top().y<l) q2.pop();
ans=max(ans,max(q1.empty()?0:l+r-q1.top().x,q2.empty()?0:-q2.top().x-(r-l)));
q1.push(data(l+r,r));
q2.push(data(-(r-l),r));
}
printf("%d",ans);
return 0;
}