[关闭]
@rebirth1120 2019-07-31T16:25:56.000000Z 字数 835 阅读 666

[CodeChef]SCHEDULE 解题报告

解题报告

解题说明

一开始写了个普通二分,连续天数一超过 就把这天取反,结果全 WA ……
后来发现这样不能取到最优方案,因为若是对一段区间的最右边的数取反,可能会影响右边的区间。
看了题解后发现不用依次枚举字符串中的每一位,只要预处理出每个连续区间的长度 就是这个区间需要取反的数的个数, 等于一的时候特判一下就行了。

代码

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. const int N=1000000+7;
  5. int T,n,k,len[N],cnt;
  6. char s[N];
  7. int spj(int k){
  8. int num=0;
  9. for(int i=1;i<=n;i++)
  10. if(i%2==k){ if(s[i]=='0') num+=1; }
  11. else { if(s[i]=='1') num+=1; }
  12. return num;
  13. }
  14. bool judge(int lim){
  15. if(lim!=1){
  16. int num=0;
  17. for(int i=1;i<=cnt;i++)
  18. if(len[i]>lim) num+=len[i]/(lim+1);
  19. return num<=k;
  20. }
  21. else{
  22. int num=min(spj(1),spj(0));
  23. return num<=k;
  24. }
  25. }
  26. int main(){
  27. //freopen("1.txt","r",stdin);
  28. cin>>T;
  29. while(T--){
  30. int lst=0,l=1,r=0,mid;cnt=0;
  31. scanf("%d%d%s",&n,&k,s+1);
  32. for(int i=1;i<=n;i++)
  33. if(s[i]!=s[i+1]){ len[++cnt]=i-lst;lst=i;r=max(r,len[cnt]); }
  34. while(l<r){
  35. mid=(l+r)>>1;
  36. if(judge(mid)) r=mid;
  37. else l=mid+1;
  38. }
  39. printf("%d\n",r);
  40. }
  41. return 0;
  42. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注