码迷,mamicode.com
首页 > 其他好文 > 详细

CF1066D Boxes Packing

时间:2018-10-20 17:26:51      阅读:216      评论:0      收藏:0      [点我收藏+]

标签:std   return   def   处理   ble   端点   从后往前   位置   efi   

传送门

这题为什么要用二分呢?/huaji

首先可以\(O(n)\)预处理出从某个物品\(i\)开始放,只放一个盒子,能放的最后物品的位置\(j\),只要用两个指针维护左右端点,每次移动一下左端点同时尽量把右端点右移救星了

然后我们要放的所有物品是原来的一个后缀,所以要从后往前放,但是直接贪心放是错的.考虑构建一棵树,根据前面对每个\(i\)预处理出的\(j\),连\((j+1,i)\)的单向边,然后从\(n+1\)开始dfs,记\(n+1\)的深度为0,那么我们不能访问深度大于\(m\)的点.记能访问到最小的点为\(y\),答案为\(n-y+1\)

#include<bits/stdc++.h>
#define LL long long
#define il inline
#define re register
#define db double
#define eps (1e-5)

using namespace std;
const int N=200000+10;
il LL rd()
{
    LL x=0,w=1;char ch=0;
    while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*w;
}
int to[N],nt[N],hd[N],tot=1;
il void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;}
int n,m,k,a[N],ans,tt=-1;
il void dfs(int x)
{
  ++tt;
  ans=max(ans,n-x+1);
  if(tt<m) for(int i=hd[x];i;i=nt[i]) dfs(to[i]);
  --tt;
}

int main()
{
  n=rd(),m=rd(),k=rd();
  for(int i=1;i<=n;i++) a[i]=rd();
  for(int i=1,su=a[1],j=1;i<=n;i++)
    {
      while(j<n&&su+a[j+1]<=k) su+=a[++j];
      add(j+1,i),su-=a[i];
    }
  dfs(n+1);
  printf("%d\n",ans);
  return 0;
}

CF1066D Boxes Packing

标签:std   return   def   处理   ble   端点   从后往前   位置   efi   

原文地址:https://www.cnblogs.com/smyjr/p/9822262.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!