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

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 }
分类:
bzoj
标签:
基础算法-贪心
, 数据结构-堆&优先队列
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现