zoukankan      html  css  js  c++  java
  • 题解[「JOISC 2017 Day 3」长途巴士]

    题目

    Luogu

    Loj

    AtCoder

    推荐Loj,有翻译。

    Sol

    一道不那么容易看出来的DP题。难得一见的(O(n^2))式子难推而且要在单调栈上二分斜率

    这道题被用来做模拟赛。wo bao li dou bu hui

    首先要把(n^2)的式子推出来。

    排序,(S_i)(S_i\%T)从大到小排 ,每个乘客按(D_i)从大到小排。

    (f_i)为考虑了前(i)个人的最小费用,(sum_i)(1 ~ i) 乘客 (C_i) 的前缀和。

    如果我们要把乘客(i)送到终点,那么:

    [f_i=f_{i-1}+W(leftlfloordfrac{X-D_i}{T} ight floor+1) ]

    意思是后面(X-D_i​)的路程都要让他下去接水。

    如果我们要一些乘客下车,让(i)能刚好留下来

    假设让(j in (0,i) ,j+1~i)的所有乘客下车:

    [f_i=min(f_i,f_j+(i-j)*W*mn_i+sum_i-sum_j) ]

    (mn_i)为到从起点走到特殊的取水点的距离时(j+1 ~ i)每个乘客必须要喝水的次数的最小值。

    特殊的取水点指的是(D_i=<S_j\%T<=D_{i+1}) ,使它能刚好让(i)乘客下车。

    [mn_i=min(leftlfloordfrac{S_j}{T} ight floor),D_i=<S_j\%P<=D_{i+1} ]

    好了,到这里我们的(n^2)就可以啦。

    下放代码。

    然后我们开始(O(nlogn))的斜率的推导。

    拆掉(min)

    [f_i=f_j+i*W*mn_i-j*W*mn_i+sum_i-sum_j) ]

    只与(i)有关的放一边,只与(j)有关的放一边:

    [f_j-sum_j=W*j*mn_i+(f_i-i*W*mn_i) ]

    括号里的是截距,要让(f_i)最小,(i*W*mn_i)又是定值,那就是让这个截距最小。

    (x=W*j)(单调),斜率(k=mn_i)

    由于(mn_i)不单调,所以我们要在单调栈里二分找与(i)匹配的斜率。

    Y(o)Y!!!

    Code

    Code1

    (O(n^2))

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=200010;
    struct xbk{ll d,c;}a[N];
    int n,m;
    ll X,w,T,s[N],f[N],mn[N],sum[N],ans=1e18;
    inline ll read(){
    	ll w=0;
    	char ch=getchar();
    	while(ch>'9'||ch<'0') ch=getchar();
    	while(ch>='0'&&ch<='9'){
    		w=(w<<3)+(w<<1)+(ch^48);
    		ch=getchar();
    	}
    	return w;
    }
    inline bool cmp(xbk a,xbk b){return a.d<b.d;}
    int main(){
    	X=read(),n=read(),m=read(),w=read(),T=read();
    	for(int i=1;i<=n;i++) s[i]=read();
    	s[++n]=X;
    	for(int i=1;i<=m;i++) a[i].d=read(),a[i].c=read();
    	sort(s+1,s+1+n);
    	sort(a+1,a+1+m,cmp);
    	for(int i=1;i<=m;i++) sum[i]=sum[i-1]+a[i].c;
    	a[m+1].d=1e13;
    	for(int i=1;i<=m;i++){
    		mn[i]=1e13;
    		for(int j=1;j<=n;j++)
    			if((s[j]%T)>a[i].d&&(s[j]%T)<a[i+1].d){mn[i]=min(mn[i],s[j]/T);}
    	} 
    	for(int i=1;i<=m;i++){
    		f[i]=f[i-1]+w*((X-a[i].d)/T+1);
    		if(mn[i]==1e13) continue;
    		for(int j=0;j<i;j++)
    			f[i]=min(f[i],f[j]+w*(i-j)*mn[i]+sum[i]-sum[j]);
    	}
    	printf("%lld
    ",f[m]+(X/T+1)*w);
    	return 0;
    }
    

    Code2

    (O(nlogn))

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=200010;
    struct xbk{ll d,c;}a[N];
    int n,m,top,stk[N];
    ll X,w,T,s[N],f[N],sum[N];
    inline ll Y(int i){return f[i]-sum[i];}
    inline double K(int i,int j){return (Y(i)-Y(j))/(i-j);}
    inline ll read(){
    	ll w=0;
    	char ch=getchar();
    	while(ch>'9'||ch<'0') ch=getchar();
    	while(ch>='0'&&ch<='9'){
    		w=(w<<3)+(w<<1)+(ch^48);
    		ch=getchar();
    	}
    	return w;
    }
    inline int getpos(ll val){
    	int l=1,r=top;
    	while(l<r){
    		int mid=(l+r)>>1;
    		if(K(stk[mid],stk[mid+1])>val) r=mid;
    		else l=mid+1;
    	}
    	return stk[r];
    }
    inline bool cmp(xbk a,xbk b){return a.d<b.d;}
    inline bool cmp1(ll a,ll b){return a%T<b%T;}
    int main(){
    	X=read(),n=read(),m=read(),w=read(),T=read();
    	for(int i=1;i<=n;i++) s[i]=read();
    	s[++n]=X;
    	for(int i=1;i<=m;i++) a[i].d=read(),a[i].c=read();
    	sort(s+1,s+1+n,cmp1);
    	sort(a+1,a+1+m,cmp);
    	for(int i=1;i<=m;i++) sum[i]=sum[i-1]+a[i].c;
    	a[m+1].d=1e13;
    	stk[++top]=0;
    	for(int i=1,j=0;i<=m;i++){
    		f[i]=f[i-1]+((X-a[i].d)/T+1)*w;
    		ll mn=1e13;
    		while(s[j+1]%T<a[i].d&&j<n) j++;
    		while(s[j+1]%T<a[i+1].d&&j<n) mn=min(mn,s[++j]/T);
    		if(mn!=1e13){
    			int pos=getpos(mn*w);
    			f[i]=min(f[i],f[pos]+(i-pos)*w*mn+sum[i]-sum[pos]);
    		}
    		while(top>1&&K(stk[top],stk[top-1])>K(stk[top],i)) top--;
    		stk[++top]=i;
    	}
    	printf("%lld
    ",f[m]+(X/T+1)*w);
    	return 0;
    }
    

    完结撒花❀

  • 相关阅读:
    设置java.library.path的值(Mac/Linux/Windows)
    英特尔老款CPU支持虚拟化对照表(转)
    长城小主机GW1等型号进BIOS的设置方法
    Mac 10.12允许任何来源
    DDos与CC攻击的简单个人理解
    Mac 10.12下iTerm2使用lrzsz上传下载文件
    Mac 10.12连接iSCSI硬盘软件iSCSI Initiator X
    华为S5300系列交换机V100R005SPH021升级补丁
    华为S5300系列交换机V100R005SPH020升级补丁
    华为S5300系列交换机V100R006SPH019升级补丁
  • 原文地址:https://www.cnblogs.com/xxbbkk/p/14526445.html
Copyright © 2011-2022 走看看