20170811

来源:互联网 发布:火柴人动图制作软件 编辑:程序博客网 时间:2024/05/29 09:07

先过了跳石头。再次辜负自己信任把scanf打成printf,要非常非常注意了……!

大致是l距离内m个点,问删去m个点所得最小相邻两点距离的最大值。(最小中求最大和最大中求最小都常用二分)

luogu2678.

#include<bits/stdc++.h>using namespace std;int a[50020]={};int l,m,n,i;bool flag(int Ans){int j=0,Now=0,x=0;//now为当前点,初值为0是为了方便加入第1个点到起点的距离。x=删去点数。while(j<n+1)//因为第n个点距离终点之间也是有距离,也是需要考虑的!{j++;if((a[j]-a[Now])<Ans) x++;//如果第j个点到当前点的距离小于正在验证的距离Ans,则需要删去第j个点,直至当前点之后Ans距离内无点。else Now=j;//当前点的Ans距离内无点时,当前点可跳到第j个点,继续清理下一段Ans距离中的点。反正是让这整段路没有间距能小于Ans。
}if(x>m) return false;//如果实现Ans所需要删的点超过m,则不可能完成。else return true;}int main(){scanf("%d%d%d",&l,&n,&m);for(i=1;i<=n;i++) scanf("%d",&a[i]);a[n+1]=l;//第n个点距离终点之间也有距离。int Left=1,Right=l,Mid;while(Left+1<Right){Mid=(Left+Right)/2;if(flag(Mid)) Left=Mid;//如果这个距离能完成,说明距离可能还能更大,所以区间右移。else Right=Mid;}if(flag(Right)) printf("%d",Right);//要注意这里!!左右两边都是可能满足flag条件的,而右边总是比左边大,为了输出最大值,要先判定右边!!!else printf("%d",Left);return 0;}
终于理清楚了。

用一个小时磨几乎一模一样的丢瓶盖,几乎想把瓶盖吞了……

scanf("%d%d&d",&n,&m);

………………………………改程序的时候,一定要改清楚了。要是是在考试做一天一夜俯卧撑仰卧起坐绕教育园跑三圈都不够我后悔的。

继续练习二分。

luogu1182.数列分段。

对于给定的一个长度为N的正整数数列A[i],现要将其分成M(M≤N)段,并要求每段连续,且每段和的最大值最小。

#include<bits/stdc++.h>using namespace std;int a[100020]={},n,m;bool flag(int s){int Summ=0,tot=1,j;//tot=分段数,初始值为1;Summ是当前已加。for(j=1;j<=n;j++){Summ=Summ+a[j];if(Summ>s) {Summ=a[j];tot++;}//如果当前累加和已超过s,则分段。}if(tot>m) return false;如果分段数超过m,则不能实现。else return true;}int main(){scanf("%d%d",&n,&m);int i;int Sum=0,Left=0;for(i=1;i<=n;i++) {  scanf("%d",&a[i]);  Sum=Sum+a[i];//右边界是数组累加和。  Left=max(Left,a[i]);//左边界点是数组中最大值。}int Right=Sum,mid;while(Left+1<Right){mid=(Left+Right)/2;if(flag(mid)) Right=mid;//如果当前值能实现,则区间左移。else Left=mid;}if(flag(Left)) printf("%d",Left);先验证左边,因为求最小值。else printf("%d",Right);return 0;}

明天再写。

--------------------是第二天写完的分割线。

又因为奇怪的原因跪了好久,不小心把一段程序误写入for循环了。

原创粉丝点击