BZOJ2726任务安排 CDQ分治维护凸包

好像不是很难,就是普通的CDQ分治,每次统计左边对右边的贡献

/*
@Date    : 2019-08-15 20:38:48
@Author  : Adscn (adscn@qq.com)
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
IL int getint()
{
    RG int xi=0;
    RG char ch=gc;
    bool f=0;
    while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10,0);
    putchar(k%10+'0');
    if(ch)putchar(ch);
}
const int N=5e5+7;
int n,S;
int c[N],t[N];
typedef long long ll;
ll f[N];
struct oper
{
    ll x,y,k;
    int id;
    bool operator <(const oper & b)const{
        return k<b.k;
    }
}qry[N],tmp[N];
inline ll Y(int j,int k){return qry[k].y-qry[j].y;}
inline ll X(int j,int k){return qry[k].x-qry[j].x;}
inline bool cmp(const oper &a,const oper &b){
    return a.x==b.x?a.y<b.y:a.x<b.x;
}
inline void cdq(int L,int R)
{
    if(L==R){
        qry[L].x=c[L];
        qry[L].y=f[L]-c[n]*t[L]+c[L]*t[L]-S*c[L];
        return;
    }
    int mid=(L+R)>>1;
    int l=L,r=mid+1;
    for(int i=L;i<=R;++i)
        if(qry[i].id>mid)tmp[r++]=qry[i];
        else tmp[l++]=qry[i];
    memcpy(qry+L,tmp+L,sizeof(oper)*(R-L+1));
    cdq(L,mid);
    static int stk[N];
    int top=0;
    for(int i=L;i<=mid;++i)
    {
        while(top>1&&(ll)Y(stk[top-1],stk[top])*X(stk[top-1],i)>(ll)Y(stk[top-1],i)*X(stk[top-1],stk[top]))--top;
        stk[++top]=i;
    }
    int h=1;
    for(int i=mid+1;i<=R;++i)
    {
        while(h<top&&(ll)Y(stk[h],stk[h+1])<(ll)qry[i].k*X(stk[h],stk[h+1]))++h;
        int I=qry[i].id,j=stk[h];
        f[I]=min(f[I],-qry[i].k*qry[j].x+qry[j].y+c[n]*(t[I]+S));
    }
    cdq(mid+1,R);
    l=L,r=mid+1;
    for(int i=L;i<=R;++i)
        if((r>R||cmp(qry[l],qry[r]))&&l<=mid)tmp[i]=qry[l++];
        else tmp[i]=qry[r++];
    memcpy(qry+L,tmp+L,sizeof(oper)*(R-L+1));
}
signed main(void)
{
    n=gi,S=gi;
    for(int i=1;i<=n;++i)t[i]=gi+t[i-1],c[i]=gi+c[i-1];
    for(int i=1;i<=n;++i)qry[i].id=i,qry[i].k=t[i],f[i]=1e18;
    sort(qry+1,qry+n+1);
    cdq(0,n);
    return pi(f[n]),0;
}

转载于:https://www.cnblogs.com/LLCSBlog/p/11361590.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值