[BZOJ1010][HNOI2008]玩具装箱[BZOJ1911][APIO2010]特别行动队[BZOJ1492][NOI2007]货币兑换 斜率优化
2016-02-16 20:45
471 查看
今天因为刷不动ydc的题,只能搞搞LCT和斜率优化,上午搞了LCT,下午搞斜率优化,其实我本来是想看冬令营的课件的,发现正好有斜率优化,也写得很好。
设dp[i]dp[i]表示前ii个玩具的答案,记s[i]s[i]为物品前缀和,那么:
dp[i]=min(dp[j]+(i−j+s[i]−s[j]−L)2),(j<i)dp[i]=min(dp[j]+(i-j+s[i]-s[j]-L)^2),(j这个很显然吧。
定义g[i]=i+s[i]−L,f[i]=i+s[i]g[i]=i+s[i]-L,f[i]=i+s[i]
我们将式子划开:
dp[i]=min(dp[j]+(g[i]−f[j])2)=min(dp[j]+g2[i]−2g[i]×f[j]+f2[j])=min(dp[j]+f2[j]−2g[i]×f[j])+g2[i]dp[i]=min(dp[j]+(g[i]-f[j])^2)
=min(dp[j]+g^2[i]-2g[i]\times f[j]+f^2[j])
=min(dp[j]+f^2[j]-2g[i]\times f[j])+g^2[i]
现在我们考虑,对于一个j1<j2j_1,j1j_1比j2j_2优的条件是什么。
显然:
dp[j1]+f2[j1]−2g[i]×f[j1]<dp[j2]+f2[j2]−2g[i]×f[j2]dp[j_1]+f^2[j_1]-2g[i]\times f[j_1]
设y[i]=dp[i]+f2[i]y[i]=dp[i]+f^2[i]
y[j1]−y[j2]<2g[i](f[j1]−f[j2])y[j_1]-y[j_2]<2g[i](f[j_1]-f[j_2])
y[j1]−y[j2]f[j1]−f[j2]>2g[i]\frac{y[j_1]-y[j_2]}{f[j_1]-f[j_2]}>2g[i]
左边像斜率的表达式吧,让它等于slop(j1,j2)slop(j_1,j_2)好了。
也就是说xx比yy优,当且仅当slop(x,y)>2g[i]slop(x,y)>2g[i]
我们按jj的顺序维护一个队列,这个队列要满足如下性质:
一、slop(x,y)>2g[i],x<yslop(x,y)>2g[i],x
证明:若slop(x,y)<2g[i]slop(x,y)<2g[i],那么对于ii以后的状态,由于gg单增,所以这个不等式恒成立,那么yy恒比xx优,故可以除掉xx。
二、slop(x,y)<slop(y,z),x<y<zslop(x,y)
证明:若slop(x,y)>slop(y,z)slop(x,y)>slop(y,z),且yy在某一个状态是最优的,有
slop(x,y)<2g[i],slop(y,z)>2g[i]⇒slop(y,z)>slop(x,y)矛盾slop(x,y)<2g[i],slop(y,z)>2g[i]\Rightarrow slop(y,z)>slop(x,y)矛盾
于是我们维护一个相邻两元素斜率递增且均大于2g[i]2g[i]最优状态可在队首取到。
那么代码就是这样的辣~(≧▽≦)/~啦啦啦
dp[i]=max(dp[j]+a(s[i]−s[j])2+b(s[i]−s[j]))+cdp[i]=max(dp[j]+a(s[i]-s[j])^2+b(s[i]-s[j]))+c
=max(dp[j]+as2[j]−2as[i]s[j]+as2[j]+bs[i]−bs[j])+c=max(dp[j]+as^2[j]-2as[i]s[j]+as^2[j]+bs[i]-bs[j])+c
设f[i]=as2[i]−bs[i]+dp[i],g[i]=as2[i]+bs[i]−2as[i]s[j]f[i]=as^2[i]-bs[i]+dp[i],g[i]=as^2[i]+bs[i]-2as[i]s[j]
原式=max(f[j]−2as[i]s[j])+g[i]+c=max(f[j]-2as[i]s[j])+g[i]+c
设x<yx,那么xx比yy优当且仅当:
f[x]−2as[i]s[x]>f[y]−2as[i]s[y]f[x]-2as[i]s[x]>f[y]-2as[i]s[y]
f[x]−f[y]>2as[i](s[x]−s[y])f[x]-f[y]>2as[i](s[x]-s[y])
f[x]−f[y]s[x]−s[y]<2as[i]\frac{f[x]-f[y]}{s[x]-s[y]}<2as[i]
同样地,我们按jj的顺序维护一个队列,这个队列要满足如下性质:
一、slop(x,y)<2as[i],x<yslop(x,y)<2as[i],x
证明:若slop(x,y)>2as[i]slop(x,y)>2as[i]等价于slop(y,x)<2as[i]slop(y,x)<2as[i],那么对于ii以后的状态,由于ss单增,所以这个不等式恒成立,那么yy恒比xx优,故可以除去xx。
这条性质决定了队列里标号小的比标号大的优,所以答案自然是队首啦,上一题也是这个道理,冬令营的课件和我完全相反,大家可以思考一下为什么我的也是对的,这个我真的强烈建议,想出来的话你也就可以说是会这种类型的斜率优化了。
二、slop(x,y)>slop(y,z),x<y<zslop(x,y)>slop(y,z),x
证明:若slop(x,y)<slop(y,z)slop(x,y),且yy在某一个状态是最优的,有
slop(x,y)>2as[i],slop(y,z)<2as[i]⇒slop(y,z)<slop(x,y)矛盾slop(x,y)>2as[i],slop(y,z)<2as[i]\Rightarrow slop(y,z)
于是我们维护一个相邻两元素斜率递减且均大于2as[i]2as[i]最优状态可在队首取到。
那么代码就是这样的辣~(≧▽≦)/~啦啦啦
请读者仔细品味这两道题的区别。
上文我提到“这一种类型的斜率优化”,没错,因为这里的斜率表达式的右边有单调性,分母也有单调性,如果没有的话,你用我的模板做题试试?
~所以,未完待续咯...
刚刚搞完冬令营的这张PPT,我来更新一下这篇博客,讲一下斜率优化的第二大类问题,斜率表达式的右边不具有单调性,分母也没有单调性,以NOI2007货币兑换作为例题。
dp[i]=max(dp[i−1],dp[j]×Ratej×Ai+BiRatej×Aj+Bj),1≤j≤i−1dp[i]=max(dp[i-1],dp[j]\times \frac{Rate_j\times A_i+Bi}{Rate_j\times A_j+B_j}),1\le j\le i-1
直接暴力dp是n2n^2的,显然超时。
考虑斜率优化。
设g(i)=dp[j]Ratej×Aj+Bjg(i)=\frac{dp[j]}{Rate_j\times A_j+B_j}
则maxmax右边=g(j)×(Ratej×Ai+Bi)=g(j)×Ratej×Ai+g(j)×Bi=g(j)\times (Rate_j\times A_i+B_i)=g(j)\times Rate_j\times A_i+g(j)\times B_i
考虑对于一个ii,有两个决策xx和yy,看在什么情况下xx优于yy。
g(x)×Ratex×Ai+g(x)×Bi>g(y)×Ratey×Ai+g(y)×Big(x)\times Rate_x\times A_i+g(x)\times B_i>g(y)\times Rate_y\times A_i+g(y)\times B_i
Ai×(g(x)×Ratex−g(y)×Ratey)>Bi×(g(y)−g(x))A_i\times(g(x)\times Rate_x-g(y)\times Rate_y)>B_i\times (g(y)-g(x))
g(x)×Ratex−g(y)×Ratey>BiAi×(g(y)−g(x))g(x)\times Rate_x-g(y)\times Rate_y>\frac{B_i}{A_i}\times (g(y)-g(x))
若g(y)−g(x)<0⇔−g(x)<−g(y)g(y)-g(x)<0\Leftrightarrow -g(x)<-g(y)
T(x,y)=g(x)×Ratex−g(y)×Ratey−g(x)−(−g(y))>BiAiT(x,y)=\frac{g(x)\times Rate_x-g(y)\times Rate_y}{-g(x)-(-g(y))}>\frac{B_i}{A_i}
若g(y)=g(x)g(y)=g(x)
RatexRatey×BiAi>BiAi\frac{Rate_x}{Rate_y}\times \frac{B_i}{A_i}> \frac{B_i}{A_i}
以上便是条件。
我们可以看到对于一个决策,我们相当于插入了一个(−g(x),g(x)∗Ratex)(-g(x),g(x)*Rate_x)的点,我们维护一个以横坐标为关键字的平衡树,那么就是在这棵树上找决策就可以了。
由上面的推导我们有对于横坐标递增的个决策x,yx,y,若T(x,y)<BiAiT(x,y)<\frac{B_i}{A_i}则xx比yy优。
根据前两题的经验,我们要维护一个相邻决策斜率单调递减的splay(可以自己证明),那么我们的答案呢?是splay的根?
不是。
我们需要在splay上找,找一个T(x,y)>BiAi,T(y,z)<BiAi,x,y,zT(x,y)>\frac{B_i}{A_i},T(y,z)<\frac{B_i}{A_i},x,y,z是相邻的,yy即就是答案。
基于这样一个证明:若T(x,y)>BiAiT(x,y)>\frac{B_i}{A_i},那么yy比xx优,同理yy比zz优,又因为斜率是单调递减的,那么yy比任何决策都优。
再来讲讲插入,我们如果要插入一个决策yy,先将其按横坐标插入到splay中,旋到根,设其两个相邻的决策为xx,zz,若T(x,y)<T(y,z)T(x,y)表明斜率出现了增的趋势,那就直接把yy删了。
插入了这个决策后,我们还要维护决策斜率的单调性,先维护这个决策左边的单调性,设yy左边的两个决策为aa,bb,若T(a,b)<T(b,y)T(a,b)则删除bb,再取aa左边一个决策继续进行比较,删除,直到满足递减即可。维护右边同理。
还有一些细节问题,就是取等号的问题,也就是上面的g(x)=g(y)g(x)=g(y)导致的,我不打算再讲了,反正我改着改着就过了,我也知道我的代码肯定还有漏洞,肯定还能被一些丧心病狂的人卡。
我用AVL伪装,纯属无聊。
至此便搞完了斜率优化。
玩具装箱
直接上方程好了。设dp[i]dp[i]表示前ii个玩具的答案,记s[i]s[i]为物品前缀和,那么:
dp[i]=min(dp[j]+(i−j+s[i]−s[j]−L)2),(j<i)dp[i]=min(dp[j]+(i-j+s[i]-s[j]-L)^2),(j这个很显然吧。
定义g[i]=i+s[i]−L,f[i]=i+s[i]g[i]=i+s[i]-L,f[i]=i+s[i]
我们将式子划开:
dp[i]=min(dp[j]+(g[i]−f[j])2)=min(dp[j]+g2[i]−2g[i]×f[j]+f2[j])=min(dp[j]+f2[j]−2g[i]×f[j])+g2[i]dp[i]=min(dp[j]+(g[i]-f[j])^2)
=min(dp[j]+g^2[i]-2g[i]\times f[j]+f^2[j])
=min(dp[j]+f^2[j]-2g[i]\times f[j])+g^2[i]
现在我们考虑,对于一个j1<j2j_1,j1j_1比j2j_2优的条件是什么。
显然:
dp[j1]+f2[j1]−2g[i]×f[j1]<dp[j2]+f2[j2]−2g[i]×f[j2]dp[j_1]+f^2[j_1]-2g[i]\times f[j_1]
设y[i]=dp[i]+f2[i]y[i]=dp[i]+f^2[i]
y[j1]−y[j2]<2g[i](f[j1]−f[j2])y[j_1]-y[j_2]<2g[i](f[j_1]-f[j_2])
y[j1]−y[j2]f[j1]−f[j2]>2g[i]\frac{y[j_1]-y[j_2]}{f[j_1]-f[j_2]}>2g[i]
左边像斜率的表达式吧,让它等于slop(j1,j2)slop(j_1,j_2)好了。
也就是说xx比yy优,当且仅当slop(x,y)>2g[i]slop(x,y)>2g[i]
我们按jj的顺序维护一个队列,这个队列要满足如下性质:
一、slop(x,y)>2g[i],x<yslop(x,y)>2g[i],x
证明:若slop(x,y)<2g[i]slop(x,y)<2g[i],那么对于ii以后的状态,由于gg单增,所以这个不等式恒成立,那么yy恒比xx优,故可以除掉xx。
二、slop(x,y)<slop(y,z),x<y<zslop(x,y)
证明:若slop(x,y)>slop(y,z)slop(x,y)>slop(y,z),且yy在某一个状态是最优的,有
slop(x,y)<2g[i],slop(y,z)>2g[i]⇒slop(y,z)>slop(x,y)矛盾slop(x,y)<2g[i],slop(y,z)>2g[i]\Rightarrow slop(y,z)>slop(x,y)矛盾
于是我们维护一个相邻两元素斜率递增且均大于2g[i]2g[i]最优状态可在队首取到。
那么代码就是这样的辣~(≧▽≦)/~啦啦啦
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #define sqr(_) ((_)*(_)) #define N 55000 #define DB double using namespace std; int n; long long c,sum ,f ,dp ,g ; int q ; inline void read() { scanf("%d%lld",&n,&c); c+=1; for(int i=1;i<=n;i++) { scanf("%lld",&sum[i]); sum[i]+=sum[i-1]; f[i]=sum[i]+(long long)i; g[i]=i+sum[i]-c; } } inline long long S(int x,int y) { return (f[x]-f[y]); } inline long long G(int x,int y) { return dp[x]-dp[y]+sqr(f[x])-sqr(f[y]); } DB slope(int x,int y) { return (DB)G(x,y)/(DB)S(x,y); } inline void go() { int first=0,last=0; for(int i=1;i<=n;i++) { while(last-first>1&&slope(q[last-2],q[last-1])>slope(q[last-1],i-1)) last--; q[last++]=i-1; while(last-first>1&&slope(q[first],q[first+1])<(DB)2*g[i])first++; dp[i]=dp[q[first]]+sqr(i-q[first]+sum[i]-sum[q[first]]-c); } printf("%lld\n",dp ); } int main() { read(); go(); return 0; }
特别行动队
同上题,设同样的状态,有:dp[i]=max(dp[j]+a(s[i]−s[j])2+b(s[i]−s[j]))+cdp[i]=max(dp[j]+a(s[i]-s[j])^2+b(s[i]-s[j]))+c
=max(dp[j]+as2[j]−2as[i]s[j]+as2[j]+bs[i]−bs[j])+c=max(dp[j]+as^2[j]-2as[i]s[j]+as^2[j]+bs[i]-bs[j])+c
设f[i]=as2[i]−bs[i]+dp[i],g[i]=as2[i]+bs[i]−2as[i]s[j]f[i]=as^2[i]-bs[i]+dp[i],g[i]=as^2[i]+bs[i]-2as[i]s[j]
原式=max(f[j]−2as[i]s[j])+g[i]+c=max(f[j]-2as[i]s[j])+g[i]+c
设x<yx,那么xx比yy优当且仅当:
f[x]−2as[i]s[x]>f[y]−2as[i]s[y]f[x]-2as[i]s[x]>f[y]-2as[i]s[y]
f[x]−f[y]>2as[i](s[x]−s[y])f[x]-f[y]>2as[i](s[x]-s[y])
f[x]−f[y]s[x]−s[y]<2as[i]\frac{f[x]-f[y]}{s[x]-s[y]}<2as[i]
同样地,我们按jj的顺序维护一个队列,这个队列要满足如下性质:
一、slop(x,y)<2as[i],x<yslop(x,y)<2as[i],x
证明:若slop(x,y)>2as[i]slop(x,y)>2as[i]等价于slop(y,x)<2as[i]slop(y,x)<2as[i],那么对于ii以后的状态,由于ss单增,所以这个不等式恒成立,那么yy恒比xx优,故可以除去xx。
这条性质决定了队列里标号小的比标号大的优,所以答案自然是队首啦,上一题也是这个道理,冬令营的课件和我完全相反,大家可以思考一下为什么我的也是对的,这个我真的强烈建议,想出来的话你也就可以说是会这种类型的斜率优化了。
二、slop(x,y)>slop(y,z),x<y<zslop(x,y)>slop(y,z),x
证明:若slop(x,y)<slop(y,z)slop(x,y),且yy在某一个状态是最优的,有
slop(x,y)>2as[i],slop(y,z)<2as[i]⇒slop(y,z)<slop(x,y)矛盾slop(x,y)>2as[i],slop(y,z)<2as[i]\Rightarrow slop(y,z)
于是我们维护一个相邻两元素斜率递减且均大于2as[i]2as[i]最优状态可在队首取到。
那么代码就是这样的辣~(≧▽≦)/~啦啦啦
请读者仔细品味这两道题的区别。
#include<ctime> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<cassert> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<climits> #define X first #define Y second #define DB double #define MP make_pair #define LL long long #define pb push_back #define sqr(_) ((_)*(_)) #define INF 0x3f3f3f3f #define pii pair<int,int> #define pdd pair<DB,DB> #define ull unsigned LL #define DEBUG(...) fprintf(stderr,__VA_ARGS__) using namespace std; const int MAXN=1000010; LL dp[MAXN],s[MAXN],a,b,c,w[MAXN]; int n,q[MAXN],first,last; LL F(int x) { return a*sqr(s[x])-b*s[x]+dp[x]; } DB slope(int x,int y) { return DB((DB)(F(x)-F(y)))/((DB)(s[x]-s[y])); } int main() { #ifndef ONLINE_JUDGE freopen("sp.in","r",stdin); freopen("sp.out","w",stdout); #endif scanf("%d",&n); scanf("%lld %lld %lld",&a,&b,&c); q[last++]=0; for(int i=1;i<=n;i++) scanf("%lld",&w[i]),s[i]=w[i]+s[i-1]; dp[1]=a*sqr(w[1])+b*w[1]+c; for(int i=2;i<=n;i++) { while(last-first>1&&slope(q[last-2],q[last-1])<slope(q[last-1],i-1))last--; q[last++]=i-1; while(last-first>1&&slope(q[first],q[first+1])>(DB)2*a*s[i])first++; dp[i]=F(q[first])-2*a*s[i]*s[q[first]]+a*sqr(s[i])+b*s[i]+c; } printf("%lld\n",dp ); }
上文我提到“这一种类型的斜率优化”,没错,因为这里的斜率表达式的右边有单调性,分母也有单调性,如果没有的话,你用我的模板做题试试?
~所以,未完待续咯...
刚刚搞完冬令营的这张PPT,我来更新一下这篇博客,讲一下斜率优化的第二大类问题,斜率表达式的右边不具有单调性,分母也没有单调性,以NOI2007货币兑换作为例题。
货币兑换
上方程:dp[i]=max(dp[i−1],dp[j]×Ratej×Ai+BiRatej×Aj+Bj),1≤j≤i−1dp[i]=max(dp[i-1],dp[j]\times \frac{Rate_j\times A_i+Bi}{Rate_j\times A_j+B_j}),1\le j\le i-1
直接暴力dp是n2n^2的,显然超时。
考虑斜率优化。
设g(i)=dp[j]Ratej×Aj+Bjg(i)=\frac{dp[j]}{Rate_j\times A_j+B_j}
则maxmax右边=g(j)×(Ratej×Ai+Bi)=g(j)×Ratej×Ai+g(j)×Bi=g(j)\times (Rate_j\times A_i+B_i)=g(j)\times Rate_j\times A_i+g(j)\times B_i
考虑对于一个ii,有两个决策xx和yy,看在什么情况下xx优于yy。
g(x)×Ratex×Ai+g(x)×Bi>g(y)×Ratey×Ai+g(y)×Big(x)\times Rate_x\times A_i+g(x)\times B_i>g(y)\times Rate_y\times A_i+g(y)\times B_i
Ai×(g(x)×Ratex−g(y)×Ratey)>Bi×(g(y)−g(x))A_i\times(g(x)\times Rate_x-g(y)\times Rate_y)>B_i\times (g(y)-g(x))
g(x)×Ratex−g(y)×Ratey>BiAi×(g(y)−g(x))g(x)\times Rate_x-g(y)\times Rate_y>\frac{B_i}{A_i}\times (g(y)-g(x))
若g(y)−g(x)<0⇔−g(x)<−g(y)g(y)-g(x)<0\Leftrightarrow -g(x)<-g(y)
T(x,y)=g(x)×Ratex−g(y)×Ratey−g(x)−(−g(y))>BiAiT(x,y)=\frac{g(x)\times Rate_x-g(y)\times Rate_y}{-g(x)-(-g(y))}>\frac{B_i}{A_i}
若g(y)=g(x)g(y)=g(x)
RatexRatey×BiAi>BiAi\frac{Rate_x}{Rate_y}\times \frac{B_i}{A_i}> \frac{B_i}{A_i}
以上便是条件。
我们可以看到对于一个决策,我们相当于插入了一个(−g(x),g(x)∗Ratex)(-g(x),g(x)*Rate_x)的点,我们维护一个以横坐标为关键字的平衡树,那么就是在这棵树上找决策就可以了。
由上面的推导我们有对于横坐标递增的个决策x,yx,y,若T(x,y)<BiAiT(x,y)<\frac{B_i}{A_i}则xx比yy优。
根据前两题的经验,我们要维护一个相邻决策斜率单调递减的splay(可以自己证明),那么我们的答案呢?是splay的根?
不是。
我们需要在splay上找,找一个T(x,y)>BiAi,T(y,z)<BiAi,x,y,zT(x,y)>\frac{B_i}{A_i},T(y,z)<\frac{B_i}{A_i},x,y,z是相邻的,yy即就是答案。
基于这样一个证明:若T(x,y)>BiAiT(x,y)>\frac{B_i}{A_i},那么yy比xx优,同理yy比zz优,又因为斜率是单调递减的,那么yy比任何决策都优。
再来讲讲插入,我们如果要插入一个决策yy,先将其按横坐标插入到splay中,旋到根,设其两个相邻的决策为xx,zz,若T(x,y)<T(y,z)T(x,y)表明斜率出现了增的趋势,那就直接把yy删了。
插入了这个决策后,我们还要维护决策斜率的单调性,先维护这个决策左边的单调性,设yy左边的两个决策为aa,bb,若T(a,b)<T(b,y)T(a,b)则删除bb,再取aa左边一个决策继续进行比较,删除,直到满足递减即可。维护右边同理。
还有一些细节问题,就是取等号的问题,也就是上面的g(x)=g(y)g(x)=g(y)导致的,我不打算再讲了,反正我改着改着就过了,我也知道我的代码肯定还有漏洞,肯定还能被一些丧心病狂的人卡。
我用AVL伪装,纯属无聊。
#include<ctime> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<iostream> #include<string> #include<cassert> #include<vector> #include<queue> #include<stack> #include<map> #include<climits> #define X first #define Y second #define DB double #define MP make_pair #define LL long long #define pb push_back #define lc son[now][0] #define rc son[now][1] #define sqr(_) ((_)*(_)) #define INF 0x3f3f3f3f #define pii pair<int,int> #define pdd pair<DB,DB> #define ull unsigned LL #define DEBUG(...) fprintf(stderr,__VA_ARGS__) const int MAXN=100100; const DB eps=1e-9; int n; DB s,A[MAXN],B[MAXN],Rate[MAXN],dp[MAXN]; DB max(DB x,DB y) { return x>y?x:y; } DB fabs(DB x) { return x<0?-x:x; } int dcmp(DB x) { if(fabs(x)<eps) return 0; return x>0?1:-1; } struct Splay{ int size[MAXN],son[MAXN][2],fa[MAXN],root; DB X[MAXN]; Splay() { memset(size,0,sizeof(size)); memset(son,0,sizeof(son)); memset(fa,0,sizeof(fa)); memset(X,0,sizeof(X)); root=0; } DB G(int x) { return dp[x]/(Rate[x]*A[x]+B[x]); } DB slope(int x,int y,int k) { DB gx=-X[x],gy=-X[y]; if(fabs(gx-gy)<eps) return Rate[x]/Rate[y]*B[k]/A[k]; return (gx*Rate[x]-gy*Rate[y])/(X[x]-X[y]); } void rotate(int x) { int y=fa[x],d=(son[y][1]==x); son[fa[y]][y==son[fa[y]][1]]=x; fa[x]=fa[y]; fa[son[x][d^1]]=y; son[y][d]=son[x][d^1]; son[x][d^1]=y; fa[y]=x; } void splay(int x,int f) { while(fa[x]!=f) { int y=fa[x]; if(fa[y]==f) { rotate(x); break; } if((son[fa[y]][1]==fa[y])^(son[fa[x]][1]==x)) { rotate(y); rotate(x); } else { rotate(x); rotate(x); } } if(f==0) root=x; } int pre(int be) { int now=son[be][0],tmp=0; while(now) tmp=now,now=son[now][1]; return tmp; } int post(int be) { int now=son[be][1],tmp=0; while(now) tmp=now,now=son[now][0]; return tmp; } void Insert(int k,int i) { X[k]=-G(k); int now=root,tmp=0,d=0; while(now) { if(dcmp(X[now]-X[k])>0) tmp=now,now=son[now][0],d=0; else tmp=now,now=son[now][1],d=1; } son[tmp][d]=k; fa[k]=tmp; splay(k,0); maintain(i); } void del(int k) { splay(k,0); if(son[k][0]==0||son[k][1]==0) { int ch=son[k][0]+son[k][1]; if(ch)fa[ch]=0; if(son[k][0])son[k][0]=0; else if(son[k][1])son[k][1]=0; return; } int Pre=pre(root); son[Pre][1]=son[k][1]; fa[son[k][1]]=Pre; son[k][0]=son[k][1]=fa[son[k][0]]=0; splay(Pre,0); } void maintain(int i) { int now=root,x1=pre(root),x2=post(root),o=root; if(x1&&x2) { if(dcmp(slope(x1,root,i)-slope(root,x2,i))<0) { del(root); return; } } while(1) { x1=pre(root); if(x1==0)break; splay(x1,0); x2=pre(root); if(x2==0)break; if(dcmp(slope(x2,x1,i)-slope(x1,now,i))<0) { del(x1); now=root; } else break; } now=o; splay(o,0); while(1) { x1=post(root); if(x1==0)break; splay(x1,0); x2=post(root); if(x2==0)break; if(dcmp(slope(now,x1,i)-slope(x1,x2,i))<0) { del(x1); //splay(x2,0); now=root; } else break; } } int find(int i) { /*if(i==42722) splay(42715,0);*/ int now=root; while(1) { //splay(now,0); int j1=pre(now),j2=post(now); if(!j1&&!j2)return now; DB a=slope(j1,now,i),b=slope(now,j2,i); if(!j1) { if(dcmp(b-B[i]/A[i])<0) return now; else now=son[now][1]; } else if(!j2) { if(dcmp(a-B[i]/A[i])>0) return now; else now=son[now][0]; } else if(dcmp(a-B[i]/A[i])>0&&dcmp(b-B[i]/A[i])<=0) return now; else if(dcmp(b-B[i]/A[i])>0) now=son[now][1]; else if(dcmp(a-B[i]/A[i])<=0) now=son[now][0]; } } void print(int now) { if(!now)return; printf("%d ",now); print(son[now][0]); print(son[now][1]); } }AVL; int main() { #ifndef ONLINE_JUDGE freopen("cash.in","r",stdin); freopen("cash.out","w",stdout); #endif scanf("%d %lf",&n,&s); for(int i=1;i<=n;i++) scanf("%lf %lf %lf",&A[i],&B[i],&Rate[i]); dp[1]=s; for(int i=2;i<=n;i++) { //DEBUG("%d\n",i); AVL.Insert(i-1,i); //printf("size::%d\n",AVL.size[AVL.root]); //AVL.print(AVL.root); int now=AVL.find(i); //printf("\n"); dp[i]=max(dp[i-1],AVL.G(now)*Rate[now]*A[i]+AVL.G(now)*B[i]); } /*for(int i=1;i<=n;i++) printf("%.3f\n",dp[i]);*/ printf("%.3lf\n",dp ); }
至此便搞完了斜率优化。
相关文章推荐
- 2014HA省队DAY8-1454. 送快递
- 文件权限详解
- 【Linux】基本知识(1)
- mybatis--总结
- Android网络连接之HttpURLConnection和HttpClient
- HVR数据复制软件部署之(一)--HUB端部署
- bzoj-2126: 排斥反应
- LeetCode2:Add Two Numbers
- HDU 5627Clarke and MST
- Spark Core Runtime分析: DAGScheduler, TaskScheduler, SchedulerBackend
- 制作U盘启动盘及安装操作系统的方法
- 创业者必备的八项“矛盾”特质
- npm package.json属性详解
- 关于glibc中的res_init()函数
- JVM调优-关于jvm的一些基本概念
- iOS之旅--scrollView实现无限轮播
- iOS之旅--开始小demo+整合
- bzoj-1098: [POI2007]办公楼biu
- 如果减少png图片的大小
- 无法启动GlassFish Server 4.1.1:服务器未运行时,HTTP或HTTPS监听程序端口已被占