CF1066D Boxes Packing
阿新 • • 發佈:2018-10-20
names main 兩個 problem 兩個指針 oid its getc \n
傳送門
這題為什麽要用二分呢?/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