码迷,mamicode.com
首页 > 其他好文 > 详细

[bzoj2687]交与并

时间:2019-08-17 14:25:31      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:最大   none   ons   spl   相同   printf   端点   直接   while   

首先算出两个区间包含的答案,然后就可以删掉所有被包含的区间,此时发现右端点也单调递增
那么对于任意一种方案,假设他选择了区间[l,r]中的某一些区间且选择了l和r,那么一定可以等价为仅选择l和r两个区间,因此答案一定是选某两个区间
简单计算后可以发现答案有单调性,所以用优先队列来找到上一个最大值即可
另外,算出包含区间的答案只需要:1.按照左端点从小到大,相同则右端点从大到小排序;2.对于每一个区间直接与上一个没有被包含的区间比较并计算即可;3.虽然这样是有反例的([1,10],[5,11]和[6,7]),但这样前两个一定更优)

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000005
 4 struct ji{
 5     int x,y;
 6     bool operator < (const ji &a)const{
 7         return (x<a.x)||(x==a.x)&&(y>a.y);
 8     }
 9 }a[N],b[N];
10 int n,m,l,r,q[N];
11 long long ans;
12 long long calc(int x,int y){
13     return 1LL*(b[y].y-b[x].x)*(b[x].y-b[y].x);
14 }
15 int main(){
16     scanf("%d",&n);
17     for(int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y);
18     sort(a+1,a+n+1);
19     b[m=1]=a[1];
20     for(int i=2;i<=n;i++)
21         if (b[m].y<a[i].y)b[++m]=a[i];
22         else ans=max(ans,1LL*(a[i].y-a[i].x)*(b[m].y-b[m].x));
23     for(int i=2;i<=m;i++){
24         while ((l<r)&&(calc(q[r-1],i)<calc(i-1,i)))r--;
25         q[r++]=i-1;
26         ans=max(ans,calc(q[l],i));
27     }
28     printf("%lld",ans);
29 }
View Code

 

[bzoj2687]交与并

标签:最大   none   ons   spl   相同   printf   端点   直接   while   

原文地址:https://www.cnblogs.com/PYWBKTDA/p/11368284.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!