JZOJ 3242. Spacing

题目

Description

排版是很有讲究的。假设稿纸的宽度是W个字符,长度不限,当你对一篇文章排版时,必须满足以下条件:

1.必须保持单词的次序。下图显示了对4个单词“This is a pen”在一张宽11字符的稿纸上排版的结果:

 

Input

输入的第一行是用空格分隔的两个正整数W和N(3<=W<=80000,2<=N<=50000),分别代表稿纸的宽度和单词数。接下来有N个正整数,第i个正整数xi代表第i个单词的长度(1<=xi<=(W-1)/2)。

Output

输出一个整数,代表最美观的排版中,最多出现多少个连续空格。
 

Sample Input

输入1:
11 4
4 2 1 3

输入2:
5 7
1 1 1 2 2 1 2

输入3:
11 7
3 1 3 1 3 3 4

输入4:
100 3
30 30 39

输入5:
30 3
2 5 3

Sample Output

输出1:
2

输出2:
1

输出3:
2

输出4:
40

输出5:
1
 

Data Constraint

2<=N<=50000

 

分析

 

  • 暴力出奇迹,能过98%??
  • 正解
  • 最大值最小显然二分
  • 再设f[i]表示当前文章右下角的单词是i能否达到目标
  • 然后枚举一个j,若j+1~i的这些单词能放进一行并满足要求
  • 判断上界下界是否满足
  • 就用f[j]更新f[i],最后枚举最后一行放哪些单词更新答案即可。

 

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 50010
 4 using namespace std;
 5 int w,n,ans,mx,p,a[N];
 6 long long sum[N];
 7 bool f[N];
 8 bool check(int x)
 9 {
10     f[0]=1,mx=-1,p=0;
11     for (int i=1;i<n;i++)
12     {
13         while (p<i&&sum[i]-sum[p]+x*(i-p-1)>=w)
14         {
15             if (f[p]) mx=p;
16             p++;
17         }
18         f[i]=(mx!=-1&&sum[i]-sum[mx]+i-mx-1<=w);
19     }
20     for (int i=n-1;i>=0;i--) 
21        if (f[i]&&sum[n]-sum[i]+n-i-1<=w) 
22             return 1;
23     return 0;
24 }
25 int main()
26 {
27     scanf("%d%d",&w,&n);
28     for (int i=1;i<=n;i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];
29     int l=1,r=w-2;
30     while (l<=r)
31     {
32         int mid=l+r>>1;
33         if (check(mid)) ans=mid,r=mid-1; else l=mid+1;
34     }
35     printf("%d",ans);
36 }

 

posted @ 2019-07-02 21:28  Melted_czj  阅读(127)  评论(0编辑  收藏  举报
body { background-color:whitesmoke; } // 修改背景颜色为半透明 #home,#sideBarMain>div,#blog-sidecolumn>div>div,.catListView{ background-color:rgba(255,255,255,0); } // 修改其他边框的颜色