【贪心+二分】codeforces D. Magazine Ad
codeforces.com/contest/803/problem/D
【题意】
给定一个字符串,字符串里可能有空格和连字符‘-’,空格和连字符的意义是一样的,都表示:能在那个位置把字符串分成两部分,且两部分分到两行去,空格或连字符留在当前行。 这个分裂操作能够使得原字符串不断变短;
问你最后获得的所有字符串(可能分裂成了多行,所以是”所有”)中最长的那个最短能够是多少;
分裂操作最多只能操作k次;
【思路】
这种题已经做过多次了,要找最长的那个最短的,直接二分查找最短值,每次贪心划分,看总行数是不是小于等于k。
时间复杂度O(|s|log|s|),|s|是字符串的长度。
【注意】
给定的字符串有空格,所以用
getchar();
gets(c);
【Accepted】
1 #include <iostream> 2 #include <stdio.h> 3 #include <cmath> 4 #include <vector> 5 #include <algorithm> 6 #include <set> 7 #include <map> 8 #include <queue> 9 #include <deque> 10 #include <stack> 11 #include <string> 12 #include <bitset> 13 #include <ctime> 14 #include<algorithm> 15 #include<cstring> 16 using namespace std; 17 typedef long long ll; 18 int n; 19 const int maxn=1e6+2; 20 char c[maxn]; 21 int len; 22 bool judge(int mid) 23 { 24 int cnt=0; 25 int l=0; 26 while(l<len) 27 { 28 if(l+mid>=len) 29 { 30 cnt++; 31 break; 32 } 33 if(c[l+mid-1]=='-'||c[l+mid-1]==' ') 34 { 35 cnt++; 36 l=l+mid; 37 } 38 else 39 { 40 int index=-1; 41 for(int i=l;i<l+mid;i++) 42 { 43 if(c[i]=='-'||c[i]==' ') 44 { 45 index=i; 46 } 47 } 48 if(index==-1) 49 { 50 return false; 51 } 52 cnt++; 53 l=index+1; 54 } 55 } 56 if(cnt<=n) 57 { 58 return true; 59 } 60 return false; 61 } 62 int main() 63 { 64 while(~scanf("%d",&n)) 65 { 66 getchar(); 67 gets(c); 68 len=strlen(c); 69 int l=0; 70 int r=len; 71 while(l<=r) 72 { 73 int mid=(l+r)>>1; 74 if(judge(mid)) 75 { 76 r=mid-1; 77 } 78 else 79 { 80 l=mid+1; 81 } 82 } 83 printf("%d\n",l); 84 } 85 return 0; 86 }