打码五分钟,Debug四小时?玄学错误求助!

P3195 [HNOI2008] 玩具装箱

居然可以无知情况推导斜率优化 (话说洛谷此相似情况好多...指发明算法)
by zzw4257 @ 2020-08-18 22:26:34


@[zzw4257](/user/40629) 众所周知 你谷人均兔铃酱
by Spasmodic @ 2020-08-18 22:46:53


```cpp #include<iostream> #include<cstdio> #define rg register #define ll unsigned long long using namespace std; ll sum[50010],f[50010],q[50010]; int n,m,L; ll Y(int j){return (f[j]+(sum[j]+j)*(sum[j]+j));} ll X(int j){return (-2*(sum[j]+j));} ll G(int i){return (i-1+sum[i]-L);} ll DG(int i){return (G(i)*G(i));} double T(int i,int j){return ((Y(i)-Y(j))/((X(i)-X(j))));} int main() { scanf("%d%d",&n,&L); for(rg int i=1;i<=n;i++){ int x; scanf("%d",&x); sum[i]=sum[i-1]+x; } int l=1,r=1; for(rg int i=1;i<=n;i++){ while(l<r&&T(q[l],q[l+1])<G(i)) l++; f[i]=Y(q[l])+DG(i)+G(i)*X(q[l]); //printf("%lld %lld %lld %lld %lld\n",Y(q[l]),DG(i),G(i),X(q[l]),G(i)*X(q[l])); while(l<r&&T(i,q[r-1])<T(q[r-1],q[r])){ swap(q[r-1],q[r]); r--; } q[++r]=i; } for(rg int j=1;j<=n;j++) printf("%lld ",f[j]); return 0; } ``` 改了一下但还是不行。那我具体说一下我的意思吧。就是将这个方程展开之后得到$f_i$=$f_j$+$(i-1+sum[i-L]-L)^2$-2(i-l+sum[i]-L)(sum[j]+j)+$(sum[j]+j)^2$ 设 ll Y(int j){return (f[j]+(sum[j]+j)*(sum[j]+j));} ll X(int j){return (-2*(sum[j]+j));} ll G(int i){return (i-1+sum[i]-L);} ll DG(int i){return (G(i)*G(i));} 然后将j1和j2分别带入就可以得到一个有点像斜率的式子了。
by doughty @ 2020-08-19 11:53:45


@[happydef](/user/121027) 有不懂的地方吗
by doughty @ 2020-08-19 11:54:22


@[zzw4257](/user/40629) ??不懂我的意思吗
by doughty @ 2020-08-19 11:55:06


```cpp //斜率优化的第一题。 //具体做法:枚举每一个玩具,计算出他们的斜率,将永远不可能成为最优解的状态丢掉。 //还要把所有过期的状态一起丢掉。 //最后就是注意long long和队不能为空等问题。 //状态转移方程为:f[i]=min{f[j-1]+(i-j+sum[i]-sum[j-1]-L)^2} //为了方便实现,同时把j改成j+1,得到: // f[i]=min{f[j]+(i-j-1+sum[i]-sum[j]-L)^2} #include<iostream> #include<cstdio> #define rg register #define ll unsigned long long using namespace std; ll sum[50010],f[50010],q[50010]; int n,m,L; ll Y(int j){return (f[j]+(sum[j]+j)*(sum[j]+j));} ll X(int j){return (-2*(sum[j]+j));} ll G(int i){return (i-1+sum[i]-L);} ll DG(int i){return (G(i)*G(i));} double T(int i,int j){return ((Y(i)-Y(j))/((X(i)-X(j))));} int main() { scanf("%d%d",&n,&L); for(rg int i=1;i<=n;i++){ int x; scanf("%d",&x); sum[i]=sum[i-1]+x; } int l=1,r=1; for(rg int i=1;i<=n;i++){ while(l<r&&T(q[l],q[l+1])<G(i)) l++; f[i]=Y(q[l])+DG(i)+G(i)*X(q[l]); //printf("%lld %lld %lld %lld %lld\n",Y(q[l]),DG(i),G(i),X(q[l]),G(i)*X(q[l])); while(l<r&&T(q[r-1],q[r])>T(q[r],i)){ //swap(q[r-1],q[r]); r--; } q[++r]=i; } for(rg int j=1;j<=n;j++) printf("%lld ",f[j]); return 0; } ``` 这个是最新改的。
by doughty @ 2020-08-19 11:58:45


我问一下你,你求斜率既不是把除改成乘,又不是浮点数,怎么就直接下去整就行了?
by Wall_breaker @ 2020-09-01 22:31:56


@[doughty](/user/59824) 全WA doge
by JohnFKennedy @ 2020-12-05 18:35:31


|