社区讨论
cdq 全WA 求条!(代码有注释)
P2497[SDOI2012] 基站建设参与者 2已保存回复 8
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @mmaa0nyx
- 此快照首次捕获于
- 2026/03/03 15:18 上周
- 此快照最后确认于
- 2026/03/06 17:25 4 天前
是分治过程除了问题,还是精度问题?
CPP#include<cstdio>
#include<cmath>
#include<algorithm>
#define y(j) (dp[j]+r[j]*x[j])
using std::min;
const int N=5e5+1;
const double INF=2e18;
long n,m;
long x[N],v[N],ri[N];
int num[N],f[N];//num存储标号,f为归并排序时的辅助数组。
double dp[N],r[N],ans=INF;
int q[N],ql,qr;//单调队列。
void cdq(int l,int _r);
int main()
{
scanf("%ld %ld",&n,&m);
for(int i=1;i<=n;++i)
{
scanf("%ld %d %ld",x+i,ri+i,v+i);
r[i]=-1.0/2.0*sqrt(ri[i]);//提前处理决策点的横坐标。
dp[i]=INF;
num[i]=i;
}
dp[1]=1.0*(v[1]);//初始化。
cdq(1,n);
for(int i=1;i<=n;++i)
if(x[i]+ri[i]>=m)
ans=min(ans,dp[i]);
printf("%.3lf",ans);
}
void cdq(int l,int _r)//_r变量名避免与数组r冲突。
{
if(l==_r) return;
int mid=(l+_r)>>1;
cdq(l,mid);//处理左半部分。
//构造左半部分的下凸包。
ql=qr=0;
q[qr]=num[l],++qr;
for(int i=l+1;i<=mid;++i)
{
while(ql+1<qr&&(y(num[i])-y(q[qr-1]))/(r[num[i]]-r[q[qr-1]])<=(y(q[qr-1])-y(q[qr-2]))/(r[q[qr-1]]-r[q[qr-2]])) --qr;
q[qr]=num[i],++qr;
}
//斜率优化
for(int i=mid+1;i<=_r;++i)
{
while(ql+1<qr&&(y(q[ql+1])-y(q[ql]))<=x[i]*(r[q[ql+1]]-r[q[ql]])) ++ql;
dp[i]=min(dp[i],dp[q[ql]]+r[q[ql]]*(1.0*x[q[ql]]-x[i])+v[i]);
}
cdq(mid+1,_r);
//对标号归并排序。
int l1=l,l2=mid+1;
for(int i=l;i<=_r;++i)
if(l2>_r||r[num[l1]]<r[num[l2]])
{
f[i]=num[l1];
++l1;
}
else
{
f[i]=num[l2];
++l2;
}
for(int i=l;i<=_r;++i)
num[i]=f[i];
return;
}
回复
共 8 条回复,欢迎继续交流。
正在加载回复...