【问题描述】
给定 N 个区间, 要求选出若干个区间 A1, A2, A3... Am (m > 1), 使得:
|A1∩A2∩A3...∩Am| * |A1∪A2∪A3...∪Am|
最大。
【输入格式】
第一行一个整数 N
接下来 N 行,每行 2 个整数 L, R, 描述一个区间。
【输出格式】
一个数, 为该式最大值。
【输入样例】
4
1 6
4 8
2 7
3 5
【输出样例】
24
【样例解释】
选(1, 6)和(2, 7)
【数据范围】
30% N≤1000
100% N≤1000000
100% L,R≤10 6
首先m=2即可取到最优解(一定).
对区间按左端点第一关键字, 右端点第二关键字排序.
维护一个单调栈. 栈内区间的长度单调递减.
每次退栈头时, 用栈头和压退栈头的区间更新答案.
压入栈头的时候用原栈头和新栈头更新.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Interval 7 { 8 long long l,r; 9 }a[1000001]; 10 int q[1000001],n; 11 long long ans; 12 bool cmp(Interval a,Interval b) 13 { 14 return (a.l<b.l||(a.l==b.l&&a.r<b.r)); 15 } 16 long long count(int x,int y) 17 { 18 if (y==0) return 0; 19 return (min(a[x].r,a[y].r)-max(a[x].l,a[y].l))*(max(a[x].r,a[y].r)-min(a[x].l,a[y].l)); 20 } 21 int main() 22 {int i,j,tail=0; 23 cin>>n; 24 for (i=1;i<=n;i++) 25 { 26 scanf("%lld%lld",&a[i].l,&a[i].r); 27 } 28 sort(a+1,a+n+1,cmp); 29 for (i=1;i<=n;i++) 30 { 31 while (tail&&a[q[tail]].r-a[q[tail]].l<=a[i].r-a[i].l) 32 { 33 ans=max(ans,count(i,q[tail])); 34 tail--; 35 } 36 tail++; 37 ans=max(ans,count(i,q[tail-1])); 38 q[tail]=i; 39 } 40 cout<<ans; 41 }
时间: 2024-11-09 13:08:27