二分专题
1532: 工资
时间限制: 1 Sec 内存限制: 128 MB提交: 120 解决: 44
[提交][状态][讨论版]
题目描述
聪哥在暑假参加了打零工的活动,这个活动分为n个工作日,每个工作日的工资为Vi。有m个结算工钱的时间,聪哥可以自由安排这些时间,也就是说什么时候拿钱,老板说的不算,聪哥才有发言权!(因为聪哥是土豪,他是老板的老板)
聪哥不喜欢身上一次性有太多的钱,于是他想安排一下拿钱的时间,使他一次性拿的钱中最大的最小。(最后一天一定要领钱)。
输入
第一行 2个数 n,m。
接下来n行,每行一个数,代表Vi。
输出
最小的最大钱数。
样例输入
7 5
100
400
300
100
500
101
400
样例输出
500
提示
样例说明
100 400//300 100//500//101//400//
“//”表示老大要去拿钱。
数据范围
20%
1<=n<=20
另 20% 1<=n<=50,Vi的和不超过1000
100% 1<=n<=100,000,m<=n,Vi<=10,000
来源
题意助读:
使他一次性拿的钱中最大的最小 就是他会拿很多次钱 然后要使得这么多次拿钱的过程中然后要使得拿完所有钱之后,那一定数量的钱中最多的那个 最少
其实意思就是
给你N个数,把他们分割成最多m个部分,每个部分的数字总和为sum[i],求一种分割方法
使得sum[i]的最大值尽量小
由题意可知m<=n
View Code
View Code
如果m越大那么答案会越小
那我们可以二分最大的sum[i]是多少,然后代回原数组中
我们每次取钱肯定是要尽量接近最大但是不要超过它
那么我们既然已经二分出一个假设的答案,那么我们只需要判断这个答案合不合理就好了
#include<algorithm> #include<cstdio> #include<cstring> #include<iostream> #include<cmath> #define maxn 100005 using namespace std; int n,m; int a[maxn],sum; int ans=0; //check表示的是 //你在当前假设的这个最大值下 //能不能在m次之内拿完所有的钱 bool check(int x) { sum=0; int owo=1; //owo是你当前的段数 for(int i=1;i<=n;++i) { sum+=a[i]; if(sum>x) { owo++; sum=a[i]; } if(owo>m)return 0; } return 1; } int main() { cin>>n>>m; int qaq=0; for(int i=1;i<=n;++i) { cin>>a[i]; qaq=max(qaq,a[i]); } int l=0,r=2100000000; while(l<=r) { int mid=l+r>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } // cout<<ans; cout<<max(ans,qaq); puts(""); return 0; } /* 题意理解: 给你N个数,把他们分割成最多m个部分,每个部分的数字总和为sum[i], 求一种分割方法使得sum[i]的最大值尽量小 */
Subsequence
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 16068 | Accepted: 6814 |
Description
A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.
Input
The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.
Output
For each the case the program has to print the result on separate line of the output file.if no answer, print 0.
Sample Input
2 10 15 5 1 3 5 10 7 4 9 2 8 5 11 1 2 3 4 5
Sample Output
2 3
Source
简述题意,找出数列中连续的一段数字串,他们的和≥s,求这个数字串的最小长度。如果没有这种数字串则输出0。
其实就是 给你n个数 在n个数中一段数列的和>=s 并要求找到数列长度最短
#include<algorithm> #include<cstdio> #include<cstring> #include<iostream> #include<cmath> #define maxn 100005 using namespace std; int n,s,t; int a[maxn]; int main() { cin>>t; for(int m=1;m<=t;++m) { cin>>n>>s; int ans=maxn; memset(a,0,sizeof(a)); for(int o=1;o<=n;++o)scanf("%d",&a[o]); for(int l=1;l<=n;++l) { int now=1,sum=0; for(int j=now;j<=now+l-1;++j) { sum+=a[j]; if(sum>=s) { ans=min(ans,l); } } for(now=2;now<=n-l+1;++now) { sum=sum-a[now-1]+a[now+l-1]; if(sum>=s) { //cout<<now<<" "<<l<<" "<<sum<<endl; ans=min(ans,l); } } } cout<<ans; puts(""); } return 0; }

浙公网安备 33010602011771号