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

删除回忆录丶 提交于 2019-11-27 11:55:37

好像不是很难,就是普通的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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!