区间(interval)

【问题描述】
给定 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 }

 

posted @ 2017-09-14 19:06  Z-Y-Y-S  阅读(786)  评论(0编辑  收藏  举报