C103 CDQ 分治+斜率优化+单调栈 P2497 [SDOI2012] 基站建设

视频链接:C103 CDQ 分治+斜率优化+单调栈 P2497 [SDOI2012] 基站建设_哔哩哔哩_bilibili

 

 

E51【模板】斜率优化DP 打印文章 - 董晓 - 博客园 (cnblogs.com)

C101【模板】单调栈 P5788 单调栈 - 董晓 - 博客园 (cnblogs.com)

Luogu P2497 [SDOI2012] 基站建设

复制代码
// CDQ分治+斜率优化+单调栈 O(nlogn)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;

#define int long long
#define mid (l+r>>1)
const int N=500005;
int n,m,x[N],r[N],v[N],q[N];
double t[N]; //t=1/(2*sqrt(r))
double f[N]; //fi表示第𝑖个点连接前面点的最小代价
struct E{double x,y;}a[N],b[N]; //状态点坐标x,y

bool cmpk(E a,E b,E c){   //比较斜率Kab>Kbc
  return (b.y-a.y)*(c.x-b.x)>(c.y-b.y)*(b.x-a.x);
}
double getf(int j,int i){ //计算fi
  return a[j].y+x[i]*a[j].x+v[i];
}
void CDQ(int l,int r){   //CDQ分治(归并排序)
  if(l==r){
    a[l].x=t[l],a[l].y=f[l]-x[l]*t[l]; //状态点坐标x,y
    return;
  }
  CDQ(l,mid);
  //此时左边已按状态坐标x(=t)升序,右边仍按基站坐标xi升序
  int top=0; 
  for(int i=l;i<=mid;i++){//用单调栈维护左边状态点的下凸壳
    while(top>1&&cmpk(a[q[top-1]],a[q[top]],a[i])) top--;
    q[++top]=i;
  }
  for(int i=mid+1;i<=r;i++){//因斜率-xi会变陡,淘汰劣质点
    while(top>1&&getf(q[top-1],i)<getf(q[top],i)) top--;
    f[i]=min(f[i],getf(q[top],i)); //用栈顶点更新右边答案
  }
  CDQ(mid+1,r);
  //在后序位置,按状态坐标x归并一下
  int i=l,j=mid+1,k=l;
  while(i<=mid&&j<=r)
    a[i].x<a[j].x ? b[k++]=a[i++]:b[k++]=a[j++];
  while(i<=mid) b[k++]=a[i++];
  while(j<=r) b[k++]=a[j++];
  for(j=l;j<=r;j++) a[j]=b[j];
}
signed main(){
  scanf("%lld%lld",&n,&m);
  for(int i=1;i<=n;i++){
    scanf("%lld%lld%lld",&x[i],&r[i],&v[i]);
    t[i]=1/(2*sqrt(r[i])); //预处理t
  }
  f[1]=v[1];
  for(int i=2;i<=n;i++) f[i]=2e18;
  
  CDQ(1,n); //CDQ分治
  double ans=2e18;
  for(int i=1;i<=n;i++) 
    if(x[i]+r[i]>=m) ans=min(ans,f[i]);
  printf("%.3lf\n",ans);
}
复制代码

 

posted @   董晓  阅读(148)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示