神仙求教 斜率优化dp我把浮点数的斜率转化为对角相乘然后WA了
查看原帖
神仙求教 斜率优化dp我把浮点数的斜率转化为对角相乘然后WA了
557756
Brilliance_Z楼主2022/9/2 13:19

我自己写的代码AC和WA交错。然后我去看题解,我看见第一篇题解的斜率是直接相除,我觉得有精度误差,把它改成对角相乘后就WA了。

然后我检查了 long longlong\ long 以及乘过去的 xx 是否为负数,没有发现任何问题。而且这道题坐标的范围是 10610^6 ,相乘后是 101210^{12} 不会爆 long longlong\ long

神仙们请问一下哪里错了?万分感谢!!!/kel

第一篇题解的代码:斜率直接相除,AC:

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ld long double

const int N=1e5+5;
const ld eps=1e-10;

ll n,m,k,sidx,ans;
struct seg{
	int x,y;
	bool operator < (const seg &v) const{
		return x!=v.x?x<v.x:y>v.y;
	}
}s[N];

ll K,f[N],g[N],num[N];
ll squ(ll x){return x*x;}
ll Y(int i){return f[i]+squ(s[i+1].x)-g[i]-K;}
ll X(int i){return s[i+1].x;}
ld slope(int i,int j){return (ld)(Y(j)-Y(i))/(X(j)-X(i));}

ll hd,tl,d[N];
bool check(){
	d[hd=tl=1]=0;
	for(int i=1;i<=n;i++){
		while(hd<tl&&slope(d[hd],d[hd+1])+eps<=2*s[i].y)hd++;
		int j=d[hd]; num[i]=num[j]+1,f[i]=f[j]+squ(s[i].y-s[j+1].x)-g[j]-K;
		if(i<n)while(hd<tl&&slope(d[tl-1],d[tl])-eps>=slope(d[tl],i))tl--;
		d[++tl]=i;
	} return num[n]<=k;
}

int main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){
		cin>>s[i].x>>s[i].y;
		if(s[i].x>s[i].y)swap(s[i].x,s[i].y);
	}
    sort(s+1,s+n+1);
	for(int i=1,r=-1;i<=n;i++)if(s[i].y>r)r=s[i].y,s[++sidx]=s[i]; n=sidx;
	for(int i=1;i<n;i++)if(s[i].y>=s[i+1].x)g[i]=squ(s[i].y-s[i+1].x+1);
	for(int i=1;i<=n;i++)s[i].y++;
	ll l=-1e12,r=0;
	while(l<=r)
	{
	    K=l+r>>1;
	    if(check()) l=K+1,ans=f[n]+K*k;
	    else r=K-1;
	}
	cout<<ans<<endl;
	return 0;
}

对角相乘的代码,WA:

#include <bits/stdc++.h>
using namespace std;

typedef __int128 i128;
#define int long long   //检查long long
#define ll long long
#define ld long double

const int N=1e5+5;

ll n,m,k,sidx,ans;
struct seg{
	int x,y;
	bool operator < (const seg &v) const{
		return x!=v.x?x<v.x:y>v.y;
	}
}s[N];

ll K,f[N],g[N],num[N];
ll squ(ll x){return x*x;}
ll Y(int i){return f[i]+squ(s[i+1].x)-g[i]-K;}
ll X(int i){return s[i+1].x;}
ld slope(int i,int j){return (ld)(Y(j)-Y(i))/(X(j)-X(i));}

ll hd,tl,d[N];
bool check(){
	d[hd=tl=1]=0;
	for(int i=1;i<=n;i++){
	    
	    //下面的代码是检查负数。提交结果是没有输出任何下面的字符
	    if(X(d[hd+1])-X(d[hd])<0) puts("!!!");
		if(i<n && X(i)-X(d[tl])<0) puts("@@@");
		if(i<n && X(d[tl])-X(d[tl-1])<0) puts("???");
		
		while(hd<tl&& (i128(Y(d[hd+1])-Y(d[hd])))<=(i128(X(d[hd+1])-X(d[hd]))*2*s[i].y))hd++;
		int j=d[hd]; num[i]=num[j]+1,f[i]=f[j]+squ(s[i].y-s[j+1].x)-g[j]-K;
		if(i<n)while(hd<tl&&(i128(Y(d[tl])-Y(d[tl-1]))*(X(i)-X(d[tl])))>=(i128(X(d[tl])-X(d[tl-1]))*(Y(i)-Y(d[tl])))) tl--;
		d[++tl]=i;
	} return num[n]<=k;
}

signed main(){
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++){
		cin>>s[i].x>>s[i].y;
		if(s[i].x>s[i].y)swap(s[i].x,s[i].y);
	} 
	sort(s+1,s+n+1);
	for(int i=1,r=-1;i<=n;i++)if(s[i].y>r)r=s[i].y,s[++sidx]=s[i]; n=sidx;
	for(int i=1;i<n;i++)if(s[i].y>=s[i+1].x)g[i]=squ(s[i].y-s[i+1].x+1);
	for(int i=1;i<=n;i++)s[i].y++;
	ll l=-1e12,r=0;
	while(l<=r)
	{
	    K=l+r>>1;
	    if(check()) l=K+1,ans=f[n]+K*k;
	    else r=K-1;
	}
	cout<<ans<<endl;
	return 0;
}
2022/9/2 13:19
加载中...