SP27098 FN16OIL - Oil 题解
一道思维量比较大,码量也比较大的题。
思路
看到坐标轴、直线,第一时间想到一次函数。
观察每一条采油线路,题目中有一句能获取到所有与石油井有公共点的石油矿内的石油(端点处或者在线段内均算),也就是说,与每个区间的具体交点并不重要。
对于任意一条不只穿过
我们可以先将虚线平移到图中的红线,再旋转至粉线使其经过两个端点。
现在考虑一般情况,当一个端点固定时,每一个油矿对答案有贡献时直线的斜率是一个区间,将这些区间从小到大排序,模拟过此端点直线的旋转,当过任意区间的左端点的时候加上这个矿井的贡献,过任意区间的右端点的时候减去这个矿井的贡献,期间记录答案取最大值即可。
做法
枚举油矿端点,计算每个油矿在矿井过此端点时对答案有贡献时斜率的区间并排序,然后旋转直线即可,
总时间复杂度
注意斜率可能是浮点数,实现时注意浮点数精度问题。
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct data{
double l_k,r_k;
int id;
}ql[2005],qr[2005];
struct line{
int x1,x2,y;
}a[2005];
int n,p,a1,b,c,cnt;
ll ans,sum;
bool cmp1(data x,data y){
return x.l_k<y.l_k;
}
bool cmp2(data x,data y){
return x.r_k<y.r_k;
}
double k(int x1,int y2,int x2,int y3){
return (double)(x1-x2)/(y2-y3);
}
int main(){
while(cin>>n){
ans=0;
for(int i=1;i<=n;i++){
cin>>a1>>b>>c;
if(a1>b)swap(a1,b);
a[i]=(line){a1,b,c};
}
for(int i=1;i<=n;i++){
cnt=0;
for(int j=1;j<=n;j++){
if(a[i].y!=a[j].y){
ql[++cnt].l_k=k(a[i].x1,a[i].y,a[j].x1,a[j].y);
ql[cnt].r_k=k(a[i].x1,a[i].y,a[j].x2,a[j].y);
ql[cnt].id=j;
if(ql[cnt].l_k>ql[cnt].r_k)swap(ql[cnt].l_k,ql[cnt].r_k);
qr[cnt]=ql[cnt];
}
}
sort(ql+1,ql+cnt+1,cmp1);
sort(qr+1,qr+cnt+1,cmp2);
sum=a[i].x2-a[i].x1;
ans=max(ans,sum);
int pos=1;
for(int j=1;j<=cnt;j++){
sum+=a[ql[j].id].x2-a[ql[j].id].x1;
for(;qr[pos].r_k<ql[j].l_k;pos++)sum=sum-(a[qr[pos].id].x2-a[qr[pos].id].x1);
ans=max(ans,sum);
}
}
cout<<ans<<endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器