斜率优化之李超线段树

三对于斜率优化,分为三种类型,一是斜率单调,第二种是是斜率不单调可以二分,第三种便是毫无规律可言的斜率情况,采用李超线段树可以在log范围内快速查询与修改,且能够胜任全部情况,代码与时间复杂度都很优秀。

一,将每个dp[i]的状态看做一条直线,提取转化成具有固定的截距,斜率的式子

二,查询操作来寻找当前决策最优的函数值

方法为在值域内带入当前xi,取函数值的最优

f为计算函数值函数 i是离散化之后的x坐标,c[i]为该离散化坐标,t为直线编号,x[t]为其固定斜率,y[t]为其固定截距

double f(int i,int t)
{
    return y[t]+x[t]*c[i];
}

李超线段树k维护的是当前x轴区域线段编号,l,r为离散化之后x坐标的范围,s[k]是当前x的最优决策线段

每次我们查询当前决策最优的情况时,带入u=当前x,逐一定位u的精确范围,然后回溯答案。

double qry(int k,int l,int r)
{

    if(l==r)
        return f(u,s[k]);
    int m=(l+r)>>1;

    return max(f(u,s[k]),u>m?qry(k<<1|1,m+1,r):qry(k<<1,l,m));

}

三,插入直线操作

插入直线操作就是将原本最优决策点替换的操作

每次我们取一段线段的中间值,如果新直线在中点处函数值大于旧直线,那么就交换决策点。

然后朝着使新直线更优的一侧进行递归,直到到达一个点时,再次比对函数值即可 

void upd(int k,int t,int l,int r)
{
    if(l==r)
    {
        if(f(l,t)>f(l,s[k]))
            s[k]=t;
        return ;
    }
    int m=(l+r)>>1;
    if(f(m,t)>f(m,s[k]))
        swap(t,s[k]);

    f(l,t)>f(l,s[k])?upd(k<<1,t,l,m):upd(k<<1|1,t,m+1,r);
}

[NOI2007] 货币兑换 - 洛谷

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

typedef long long int ll;

double a[100000+10],b[100000+10],c[100000+10],d[100000+10],k[100000+10],x[100000+10],y[100000+10],r[100000+10];
int n,u;
double f;
int mp[100000*4+10];

# define getval( i, id) (c[i]*x[id]+y[id])

double query(int root,int l,int r)
{
    if(l==r)
    {
        return getval(u,mp[root]);
    }

    int mid=(l+r)>>1;

    return max(getval(u,mp[root]),u>mid?query(root<<1|1,mid+1,r):query(root<<1,l,mid));

}

void update(int root,int t,int l,int r)
{
    if(l==r)
    {
        if(getval(l,t)>getval(l,mp[root]))
            mp[root]=t;
        return ;
    }
    int mid=(l+r)>>1;

    if(getval(mid,t)>getval(mid,mp[root]))
        swap(mp[root],t);

    getval(l,t)>getval(l,mp[root])?update(root<<1,t,l,mid):update(root<<1|1,t,mid+1,r);
}
int main()
{

  cin>>n>>f;

  for(int i=1;i<=n;i++)
  {

     scanf("%lf%lf%lf",&a[i],&b[i],&r[i]);

      c[i]=a[i]/b[i];
      d[i]=c[i];
  }

  sort(c+1,c+1+n);

  for(int i=1;i<=n;i++)
  {
      u=lower_bound(c+1,c+1+n,d[i])-c;

      f=max(f,b[i]*query(1,1,n));

      x[i]=f/(a[i]+b[i]/r[i]);
      y[i]=x[i]/r[i];

      update(1,i,1,n);

  }

  cout<<fixed<<setprecision(3)<<f<<endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
引用和提到,Linux下安装ffmpeg是非常方便的。下面给出在Linux上安装ffmpeg的步骤: 1. 首先,需要安装Cygwin。Cygwin是一个在Windows上运行类似于Linux的环境的工具。可以从官方网站上下载并安装。 2. 安装完Cygwin后,打开终端,输入以下命令下载x264源代码并进行编译: ``` wget http://mirror.yandex.ru/mirrors/ftp.videolan.org/x264/snapshots/last_x264.tar.bz2 bunzip2 last_x264.tar.bz2 tar -vxf last_x264.tar cd last_x264 ./configure --enable-static --enable-shared --disable-asm --disable-avs make && sudo make install ``` 3. 然后,从ffmpeg官网下载ffmpeg源代码,并进行编译。编译方法可以参考官方文档或者在终端中输入以下命令: ``` wget http://ffmpeg.org/releases/ffmpeg-[版本号].tar.gz tar -xzvf ffmpeg-[版本号].tar.gz cd ffmpeg-[版本号] ./configure --enable-shared make sudo make install ``` 其中,是你想要安装的ffmpeg的版本号。 4. 编译完成后,就可以使用ffmpeg了。可以通过在终端中输入`ffmpeg`命令来验证是否安装成功。 请注意,以上步骤仅适用于在Linux系统上安装ffmpeg。如果你是在其他操作系统上进行安装,请参考相关的文档或者教程。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Windows下编译安装 FFmpeg](https://blog.csdn.net/heng615975867/article/details/119821945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值