poj3273——经典的二分优化

poj3273——经典的二分优化

Monthly Expense

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 16522   Accepted: 6570

Description

Farmer John is an astounding accounting wizard and has realized he might run out of money to run the farm. He has already calculated and recorded the exact amount of money (1 ≤moneyi ≤ 10,000) that he will need to spend each day over the next N (1 ≤ N ≤ 100,000) days.

FJ wants to create a budget for a sequential set of exactly M (1 ≤ M ≤ N) fiscal periods called "fajomonths". Each of these fajomonths contains a set of 1 or more consecutive days. Every day is contained in exactly one fajomonth.

FJ‘s goal is to arrange the fajomonths so as to minimize the expenses of the fajomonth with the highest spending and thus determine his monthly spending limit.

Input

Line 1: Two space-separated integers: N and M 
Lines 2..N+1: Line i+1 contains the number of dollars Farmer John spends on the ith day

Output

Line 1: The smallest possible monthly limit Farmer John can afford to live with.

Sample Input

7 5
100
400
300
100
500
101
400

Sample Output

500

题意:将一个数组分成M段,使最大段和最小,求最大段和的最小值思路:考虑两种极端情况:分成1组,所有的元素作为一组,则最大段和为总和Sum;分成M组,每一个元素单独作为一组,则最大段和为最大值Max。由于1<=M<=N;故最大段和肯定在[Max,Sum]的范围内,具体等于多少取决于组数M。因此在[Max,Sum]内从大到小进行遍历limit,若找到一个limit,分组数为group,如果group<=M,说明还可以继续分组使limit更小,因此继续查找,如果group>M,说明不能再分了,前一个查找的limit在M分组之下最小值了,直接退出遍历,答案即为limit。此做法时间复杂度为o(N^2),二分优化,在[Max,Sum]进行二分查找,可以使时间复杂度将为o(N*logN)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>

using namespace std;

typedef long long ll;
const int maxn=1000100;
const ll INF=(1<<28);

int N,M;
ll a[maxn];

bool judge(int limit)
{
    int group=1;
    ll sum=0;
    for(int i=0;i<N;i++){
        if(sum+a[i]<=limit) sum+=a[i];
        else{
            sum=a[i];
            group++;
        }
    }
    if(group<=M) return true;///分的组数少了,还可以再分使limit更小
    return false;
}

ll BinSearch(ll low,ll high)
{
    while(low<high){
        ll mid=(low+high)/2;
        if(judge(mid)) ///期望mid越小越好,符合条件,继续找更小的
            high=mid;
        else low=mid+1; ///不符合条件,向更大的找
    }
    return high;
}

int main()
{
    while(cin>>N>>M){
        ll Max=-INF,Sum=0;
        for(int i=0;i<N;i++){
            cin>>a[i];
            Sum+=a[i];
            if(a[i]>Max) Max=a[i];
        }
        cout<<BinSearch(Max,Sum)<<endl;
    }
    return 0;
}

时间: 2024-10-14 00:37:56

poj3273——经典的二分优化的相关文章

poj3258——二分优化

poj3258——二分优化 River Hopscotch Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8201   Accepted: 3531 Description Every year the cows hold an event featuring a peculiar version of hopscotch that involves carefully jumping from rock to rock

最长上升子序列的二分优化

http://blog.csdn.net/wall_f/article/details/8295812 作者写的太好了,转载一下~ 我简单总结一下,我的理解. 最长上升子序列的转移方程:b[k]=max(max(b[j]|a[j]<a[k],j<k)+1,1); 其优化主要在求解当前最长长度是要查找前面的b数组中是否有最大的值,且当前期a[j]<a[k],因此就是要找小于当前值的最大值. 所以我们一般需要从1~k-1扫描一遍找到最大值,复杂度为o(n^2),耗时太长. 因此我们可以直接记

HDU 1025:Constructing Roads In JGShining&#39;s Kingdom(LIS+二分优化)

http://acm.hdu.edu.cn/showproblem.php?pid=1025 Constructing Roads In JGShining's Kingdom Problem Description JGShining's kingdom consists of 2n(n is no more than 500,000) small cities which are located in two parallel lines.Half of these cities are r

硬币问题 (dp,多重背包的二分优化)

题目描述 给你n种硬币,知道每种的面值Ai和每种的数量Ci.问能凑出多少种不大于m的面值. 输入 有多组数据,每一组第一行有两个整数 n(1≤n≤100)和m(m≤100000),第二行有2n个整数,即面值A1,A2,A3,…,An和数量C1,C2,C3,…,Cn (1≤Ai≤100000,1≤Ci≤1000).所有数据结束以2个0表示. 输出 每组数据输出一行答案. 样例输入 3 10 1 2 4 2 1 1 2 5 1 4 2 1 0 0 样例输出 8 4 背包问题的复杂度是n*m,这题如果

POJ 3903:Stock Exchange(裸LIS + 二分优化)

http://poj.org/problem?id=3903 Stock Exchange Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5983   Accepted: 2096 Description The world financial crisis is quite a subject. Some people are more relaxed while others are quite anxious. J

HDU 1025 LIS二分优化

题目链接: acm.hdu.edu.cn/showproblem.php?pid=1025 Constructing Roads In JGShining's Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 28755    Accepted Submission(s): 8149 Problem Description

51nod 1267二分+优化试验场

最初,最开始的时候,万能的学姐曾经警告过我们,千万别用什么老狮子MAP,手撸map或者字典树...当时不甚理解...今天...这题直接卡掉了我的MAP,但是使用朴素方法进行二分...不加优化,,都不需要这个架势...直接相差了将近十倍,在我开了优化之后快了20倍左右.... 上代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const long long MAXN=1233; 5 6 7 class node 8 { 9 pub

HDU 5652 India and China Origins 二分优化+BFS剪枝

题目大意:给你一个地图0代表可以通过1代表不可以通过.只要能从第一行走到最后一行,那么中国与印度是可以联通的.现在给你q个点,每年风沙会按顺序侵蚀这个点,使改点不可通过.问几年后中国与印度不连通.若一直联通输出-1. 题目思路:看数据这道题就是卡时间的,我们的基本思路是每当风沙侵蚀一个点,我们就进行一次广搜,看看图上下是否联通,我们应尽可能的去优化这个过程. 所以我们可以在遍历年的时候用二分查找: 若当年图可以上下联通,则继续向右查找 若当年图上下无法联通,则向左查找 剪枝: 为了省时间我们应该

[POJ1631]Bridging signals (DP,二分优化)

题目链接:http://poj.org/problem?id=1631 就是求一个LIS,但是范围太大(n≤40000),无法用常规O(n²)的朴素DP算法,这时需要优化. 新加一个数组s[]来维护长度当LIS的长度为len时候需要的数组a中的最小数字的值,可以证明这个数组是严格单调递增的,因此可以二分确定每次枚举到a[i]的时候,a[i]在这个数组中所处的位置(下标),也就是a[i]数字时此时之前算过的LIS的长度.之后更新s数组和ans即可.对于最长下降自序列此方法同样适用,但是需要注意那时