SDNU1331 二分法求,确定划分次数后的最小连续区间和

原创 2016年06月01日 11:45:42


0)

(这个题的数据OJ没有补充,0<=N<=100000,K<=N,A[i]<=10^9)

二分法是有规律的暴力,那么二分的数列一定是有某种顺序,使得二分得到的数如果不符合某个条件,可以按规则再往左二分或再往右二分。

1)

之前用二分模拟划分情况,非常笨也非常麻烦,是不符合为了简洁高效而使用二分的思想。事后才知道,直接二分答案即可,因为二分效率非常高,找到答案所在的大概的区间位置,也就是二分所有可能的区间和,也不过是log(10^5)≈16,再遍历一遍这个找到的大概区间,从而找到最小的和,哪怕是最坏情况下,把所有和再遍历一遍,是O(n)=10^5,总共也不过1.6*10^6,是可以接受的。

还是应该把思路打开,用思想去做题,而不要太拘泥于题目的具体场景。

补充:如果加上 #include <iostream> 与 using namespace std(同时存在),自己定义的left 、right 与标准库中的冲突,因此编译报错二义性问题——...main.cpp|41|error: reference to 'left' is ambiguous| ......

//#include <iostream>
#include <string>
#include <stdio.h>

//using namespace std;
int n,k;
long long int sum=0;
int a[100010];
long long int left=0;
long long int right=0;
long long int mid;
int Date(){
    int cnt=1;
    long long int temp=mid;
    for(int i=1;i<=n;i++){
        if(mid<a[i]){
            return -1;//当前二分到的数,过小
        }
        if(temp>=a[i]) temp-=a[i];
        else if(temp<a[i]){
            cnt++;
            temp=mid-a[i];
        }
    }
    if(cnt==k) return 0;
    else if(cnt<k) return 1;//当前二分到的数,过大
    else return -1;
}
int main()
{

    while(~scanf("%d %d",&n,&k))
    {
        sum=0;
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }

        left=0;
        right=sum;
        mid=(left+right)/2;
        int cur=Date();
        while(cur){
            if(cur==-1) left=mid+1;
            else if(cur==1) right=mid-1;
            mid=(left+right)/2;
            cur=Date();
        }
        for(mid=left;mid<=sum;mid++){
            if(Date()==0){
                printf("%ld\n",mid);
                break;
            }
        }
    }
    return 0;
}
2)

Description

有n个菜鸟站成一排,Jason要按顺序虐他们一下。虐第i个菜鸟需要花费掉A[i]点RP,现在Jason打算分k天虐完这些菜鸟。Jason每天的RP总数是固定的,为了使RP最低的时候不会过低导致杯具,他希望这k天中虐菜花费RP最多的一天,花费的RP尽量少。求Jason在花费RP最多那天花费了了多少RP。

Input

第一行两个正整数n,k。

第二行为此数列A[i]

Output

一个数,为题目所求答案。

Sample Input

5 22 1 3 4 5

Sample Output

9

Hint

n ≤ 100,000, k ≤ n, ai ≤ 10^9


版权声明:本文为博主原创文章,未经博主允许不得转载。

5-18 二分法求多项式单根 (20分)

5-18 二分法求多项式单根   (20分) 二分法求函数根的原理为:如果连续函数f(x)f(x)在区间[a, b][a,b]的两个端点取值异号,即f(a)f(b)f(a)f(b)0...
  • ccDLlyy
  • ccDLlyy
  • 2016年07月29日 22:40
  • 442

《C/C++/Java/Pascal 程序设计基础》习题集 解题2

题目链接:http://www.patest.cn/contests/basic-programming ,总体说来都是基础题,节省时间,只做了分值20的题目。 解题1链接:http://blog.c...
  • wyh7280
  • wyh7280
  • 2015年07月29日 15:35
  • 1023

5-18 二分法求多项式单根

二分法求函数根的原理为:如果连续函数f(x)在区间[a,b]的两个端点取值异号,即f(a)f(b)0,则它在这个区间内至少存在1个根r,即f(r)=0。 二分法的步骤为: 检查区间长度,如...
  • sunhero2010
  • sunhero2010
  • 2015年10月19日 21:35
  • 2115

5-18 二分法求多项式单根 (20分)

#include double f(double x); double a1,a2,a3,a4; int main() { double a,b; scanf("%lf %lf %lf...
  • jameszjd
  • jameszjd
  • 2016年07月06日 22:14
  • 110

循环-08. 二分法求多项式单根(20)

循环-08. 二分法求多项式单根(20) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 8000 B 判题程序 ...
  • weixin_sysu
  • weixin_sysu
  • 2014年07月23日 08:28
  • 835

LeetCode一道题:回文数划分的最小次数

public class Sholution { private boolean isPalindrome(char[] ch, int i,int j){ while(i
  • u011569303
  • u011569303
  • 2013年09月22日 13:30
  • 803

回文最小划分次数(dp之路)

题目: 对输入的字符串划分为一组回文字符串,最小的分割次数 转换方程:dp[j]=min(dp[j],dp[k-1]+1) 代码: #include #include #inclu...
  • jklcl
  • jklcl
  • 2017年02月08日 17:26
  • 764

二分法求函数根

http://www.patest.cn/contests/mooc-ds/03-1 二分法求函数根的原理为:如果连续函数f(x)在区间[a, b]的两个端点取值异号,即f(a)f(b) ...
  • BaibuT
  • BaibuT
  • 2015年01月12日 22:07
  • 224

【算法设计与数据结构】二分法解决最大值最小化问题——入门篇

问题描述把一个包含n个正整数的序列划分成m个连续的子序列。设第i个序列的各数之和为S(i),求所有S(i)的最大值最小是多少? 例子: 序列1 2 3 2 5 4划分为3个子序列的最优方案为 1 2...
  • jiange_zh
  • jiange_zh
  • 2015年09月03日 13:54
  • 1831
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SDNU1331 二分法求,确定划分次数后的最小连续区间和
举报原因:
原因补充:

(最多只允许输入30个字)