1 solutions
-
0
POJ 2759 Distributing tasks/Lyk Love painting 题解
知识点
二分,DP,尺取。
分析
约定 分别表示第一排树种树难度、第二排树种树难度以及一二排树种树难度的和,而 分别是它们的前缀和。
首先想到有二分加 DP 决策,那么我们可以有下面集中做法。
法 1
二分答案 后,设出 DP 状态 表示:前 棵树最少需要 个人种。
那么很显然,在 的转移可以是两种:
-
两排一起种:(要满足能够把每个矩形和都划分为 的)
$$f_i \gets f_j + \lceil \frac{C_i-C_j}{lim} \rceil \\$$ -
两个都单排种:
其中 分别表示将第一和二排树 中划分成 的块的最少数量。
那么看着复杂度就不对,考虑优化。
-
两排一起种:(要满足能够把每个矩形和都划分为 的)
我们只要考虑将两排划分成一块 时的情况,也就是选最小的满足 的 (如果没有就跳过)。
-
两个都单排种:
我们其实可以考虑两排分别从 按一整块划分出来的块往前跳,又发现被转移的点 取决于跳回去后在较大位置的那个点,所以每次跳还在较大位置的那个点即可,复杂度不超过 。
二分开始时将每次 往前 跳 能到的最远的位置提前预处理出来即可。
那么这样的复杂度为 ,虽然跑不满,但是算出来还是超过了上界。
法 2
考虑更换状态,设 表示:前 个人最多能种到前 棵树。那么转移和上面差不多。
首先二分开始时将每次 往后 跳 能到的最远的位置提前预处理出来即可。
-
两排一起种:(要满足能够把每个矩形和都划分为 的)
我们只要考虑将两排划分成一块 时的情况,只要考虑 即可。
-
两个都单排种:
也是考虑两排分别从 按一整块划分出来的块往后跳,又发现被转移的点 取决于跳回去后在较小位置的那个点,所以每次跳还在较小位置的那个点即可,复杂度不超过 。
复杂度变为 。
代码
法 1
int n,m,mx; int a[N],b[N],c[N],pa[N],pb[N],pc[N]; int f[N]; ll ans; ll A[N],B[N],C[N]; bool Check(const ll lim) { auto Init=[&](int *a,int *pa,ll *A) { pa[0]=0; FOR(i,1,n) { pa[i]=pa[i-1]; while(A[i]-A[pa[i]]>lim)++pa[i]; } }; Init(a,pa,A),Init(b,pb,B),Init(c,pc,C),f[0]=0; FOR(i,1,n) { f[i]=pc[i]<i?f[pc[i]]+1:INF; int ia(i),ib(i),cnt(0); while(cnt<=m&&(ia||ib))ia>ib?ia=pa[ia]:ib=pb[ib],++cnt,tomin(f[i],f[max(ia,ib)]+cnt); if(f[i]>m)return false; } return true; } signed main() { #ifdef Plus_Cat freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout); #endif // Plus_Cat I(n,m); FOR(i,1,n)I(a[i]),tomax(mx,a[i]),A[i]=A[i-1]+a[i]; FOR(i,1,n)I(b[i]),tomax(mx,b[i]),B[i]=B[i-1]+b[i]; FOR(i,1,n)c[i]=a[i]+b[i],C[i]=C[i-1]+c[i]; for(ll l(mx),r(C[n]),mid((l+r)>>1); l<=r; mid=(l+r)>>1)Check(mid)?ans=mid,r=mid-1:l=mid+1; O(ans,'\n'); return 0; }法 2
int n,m,mx; int a[N],b[N],c[N],pa[N],pb[N],pc[N]; int f[M]; ll ans; ll A[N],B[N],C[N]; bool Check(const ll lim) { //Init pa[n]=n,pb[n]=n,pc[n]=n; DOR(i,n-1,0) { pa[i]=pa[i+1],pb[i]=pb[i+1],pc[i]=pc[i+1]; while(A[pa[i]]-A[i]>lim)--pa[i]; while(B[pb[i]]-B[i]>lim)--pb[i]; while(C[pc[i]]-C[i]>lim)--pc[i]; } //DP RCL(f,0,int,m+1); FOR(i,0,m) { if(f[i]>=n)return true; //a,b int ia(f[i]),ib(f[i]),cnt(0); while(i+cnt<=m)ia<ib?ia=pa[ia]:ib=pb[ib],++cnt,tomax(f[i+cnt],min(ia,ib)); //c tomax(f[i+1],pc[f[i]]); } return f[m]>=n; } signed main() { #ifdef Plus_Cat freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout); #endif // Plus_Cat I(n,m); FOR(i,1,n)I(a[i]),tomax(mx,a[i]),A[i]=A[i-1]+a[i]; FOR(i,1,n)I(b[i]),tomax(mx,b[i]),B[i]=B[i-1]+b[i]; FOR(i,1,n)c[i]=a[i]+b[i],C[i]=C[i-1]+c[i]; if(m==1)return O(C[n],'\n'),0; for(ll l(mx),r(C[n]),mid((l+r)>>1); l<=r; mid=(l+r)>>1)Check(mid)?ans=mid,r=mid-1:l=mid+1; O(ans,'\n'); return 0; }
-
Information
- ID
- 1401
- Time
- 1000ms
- Memory
- 256MiB
- Difficulty
- 10
- Tags
- (None)
- # Submissions
- 4
- Accepted
- 1
- Uploaded By