1 条题解
-
0
自动搬运
来自洛谷,原作者为

NahX_
梨雨温琐忆搬运于
2025-08-24 22:48:02,当前版本为作者最后更新于2024-11-20 21:14:07,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题意简明,不再阐述。
首先可以对当前两行(假设为第 , 行)的情况分类。
- 。
此时可以分为三种情况。
一种是从 0 处调 件物品(),这 件物品显然对应第 行 ,然后第 行的后 个物品去到 。
另一种是从 处调 件物品(),这 件物品显然对应第 行 ,然后第 行的前 个物品去到 0。
还有一种是从 0 处调 件物品,从 处调 件物品(),分别对应 行 和 ,第 行的物品则对应第 行的 。
发现最小代价无论在哪种情况中取到其代价随 变化所形成的图像都是单谷的(第三种情况看作 ),于是可以三分,对于每一种情况都三分 找到最小代价最后三种情况取最小即可。
- 。
此时也是分三种情况,前两种情况与 时的前两种情况相同,第三种情况变为调前 个元素到 0,调后 个元素到 ()。
最小代价无论在哪种情况中取到其代价随 变化所形成的图像也是单谷的,同上三分求最小代价即可。
时间复杂度 。
#include<bits/stdc++.h> using namespace std; #define mp make_pair #define int long long #define db double #define endl '\n' #define lowbit(x) x&-x #define intz(x,a) memset(x,a,sizeof(x)) const int N=5e5+5; int s[N];vector<int>p[N]; signed main(){int n,d;cin>>n>>d; for(int i=1;i<=n;i++){cin>>s[i];p[i].resize(s[i]+5); for(int j=1;j<=s[i];j++)cin>>p[i][j]; } for(int i=1;i<n;i++){ if(s[i]<=s[i+1]){int l=0,r=s[i+1],ans=(1ll<<63)-1; while(l<=r){int mid0=l+(r-l)/3,mid1=r-(r-l)/3,sum0=0,sum1=0; for(int j=1;j<=s[i+1];j++) if(j<=mid0)sum0+=p[i+1][j]; else if(j<=mid0+s[i])sum0+=abs(p[i+1][j]-p[i][j-mid0]); else sum0+=d-p[i+1][j]; for(int j=s[i+1]-mid0+1;j<=s[i];j++)sum0+=min(p[i][j],d-p[i][j]); for(int j=1;j<=s[i+1];j++) if(j<=mid1)sum1+=p[i+1][j]; else if(j<=mid1+s[i])sum1+=abs(p[i+1][j]-p[i][j-mid1]); else sum1+=d-p[i+1][j]; for(int j=s[i+1]-mid1+1;j<=s[i];j++)sum1+=min(p[i][j],d-p[i][j]); if(sum0>=sum1)l=mid0+1,ans=min(ans,sum1);else r=mid1-1,ans=min(ans,sum0); }l=0,r=s[i+1]; while(l<=r){int mid0=l+(r-l)/3,mid1=r-(r-l)/3,sum0=0,sum1=0; for(int j=s[i+1];j;j--) if(j>=s[i+1]-mid0+1)sum0+=d-p[i+1][j]; else if(j>=s[i+1]-mid0-s[i]+1)sum0+=abs(p[i+1][j]-p[i][j-s[i+1]+mid0+s[i]]); else sum0+=p[i+1][j]; for(int j=1;j<=-s[i+1]+mid0+s[i];j++)sum0+=min(p[i][j],d-p[i][j]); for(int j=s[i+1];j;j--) if(j>=s[i+1]-mid1+1)sum1+=d-p[i+1][j]; else if(j>=s[i+1]-mid1-s[i]+1)sum1+=abs(p[i+1][j]-p[i][j-s[i+1]+mid1+s[i]]); else sum1+=p[i+1][j]; for(int j=1;j<=-s[i+1]+mid1+s[i];j++)sum1+=min(p[i][j],d-p[i][j]); if(sum0>=sum1)l=mid0+1,ans=min(ans,sum1);else r=mid1-1,ans=min(ans,sum0); }cout<<ans<<endl; }else{int l=0,r=s[i],ans=(1ll<<63)-1; while(l<=r){int mid0=l+(r-l)/3,mid1=r-(r-l)/3,sum0=0,sum1=0; for(int j=1;j<=s[i];j++) if(j<=mid0)sum0+=p[i][j]; else if(j<=mid0+s[i+1])sum0+=abs(p[i][j]-p[i+1][j-mid0]); else sum0+=d-p[i][j]; for(int j=s[i]-mid0+1;j<=s[i+1];j++)sum0+=min(p[i+1][j],d-p[i+1][j]); for(int j=1;j<=s[i];j++) if(j<=mid1)sum1+=p[i][j]; else if(j<=mid1+s[i+1])sum1+=abs(p[i][j]-p[i+1][j-mid1]); else sum1+=d-p[i][j]; for(int j=s[i]-mid1+1;j<=s[i+1];j++)sum1+=min(p[i+1][j],d-p[i+1][j]); if(sum0>=sum1)l=mid0+1,ans=min(ans,sum1);else r=mid1-1,ans=min(ans,sum0); }l=0,r=s[i]; while(l<=r){int mid0=l+(r-l)/3,mid1=r-(r-l)/3,sum0=0,sum1=0; for(int j=s[i];j;j--) if(j>=s[i]-mid0+1)sum0+=d-p[i][j]; else if(j>=s[i]-mid0-s[i+1]+1)sum0+=abs(p[i][j]-p[i+1][j-s[i]+mid0+s[i+1]]); else sum0+=d-p[i][j]; for(int j=1;j<=-s[i]+mid0+s[i+1];j++)sum0+=min(p[i+1][j],d-p[i+1][j]); for(int j=s[i];j;j--) if(j>=s[i]-mid1+1)sum1+=d-p[i][j]; else if(j>=s[i]-mid1-s[i+1]+1)sum1+=abs(p[i][j]-p[i+1][j-s[i]+mid1+s[i+1]]); else sum1+=d-p[i][j]; for(int j=1;j<=-s[i]+mid1+s[i+1];j++)sum1+=min(p[i+1][j],d-p[i+1][j]); if(sum0>=sum1)l=mid0+1,ans=min(ans,sum1);else r=mid1-1,ans=min(ans,sum0); } cout<<ans<<endl; } } return 0; }
- 1
信息
- ID
- 8759
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者