• 【TYVJ】1359


    http://tyvj.cn/Problem_Show.aspx?id=1359

    一开始是一眼看出是二分的,因为这里有单调性,因为取钱是一次取完并且是连续的。

    所以最优取法就是准备达到某个价值再取。最优里边包含了次优,也就是取不到m次我就能取完就一定能够取m次能够取完,只要在取法那里随便取就行了,保证不超过这个某个价值

    于是我们可以二分这个价值,看看能不能最优法取完并且次数小于m。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=100005;
    int n, m, a[N];
    
    inline const bool check(const int &x) {
    	int sum=0, t=0, i;
    	for(i=1; i<=n; ++i) {
    		sum+=a[i];
    		if(sum>x) sum=a[i], ++t;
    		if(t>=m) return 0; //这里要注意,因为此时一定还有没取完的,所以==m的时候就要退出了
    	}
    	return 1;
    }
    
    int main() {
    	read(n); read(m);
    	int mx=0, sum=0;
    	for1(i, 1, n) { read(a[i]); mx=max(mx, a[i]); sum+=a[i]; }
    	int l=mx, r=sum, mid;
    	while(l<=r) {
    		mid=(l+r)>>1;
    		if(check(mid)) r=mid-1;
    		else l=mid+1;
    	}
    	print(r+1);
    	return 0;
    }
    

     因为范围很大,所以我们二分的范围要适当做点技巧。


    描述 Description

        高考结束后,同学们大都找到了一份临时工作,渴望挣得一些零用钱。从今天起,Matrix67将连续工作N天(1<=N& lt;=100 000)。每一天末他可以领取当天及前面若干天里没有领取的工资,但他总共只有M(1<=M<=N)次领取工资的机会。 Matrix67已经知道了在接下来的这N天里每一天他可以赚多少钱。为了避免自己滥用零花钱,他希望知道如何安排领取工资的时间才能使得领到工资最多的 那一次工资数额最小。注意Matrix67必须恰好领工资M次,且需要将所有的工资全部领走(即最后一天末需要领一次工资)。

    输入格式 InputFormat

        第一行输入两个用空格隔开的正整数N和M
        以下N行每行一个不超过10000正整数,依次表示每一天的薪水。

    输出格式 OutputFormat

       输出领取到的工资的最大值最小是多少。

    样例输入 SampleInput [复制数据]

    7 5
    100
    400
    300
    100
    500
    101
    400

    样例输出 SampleOutput [复制数据]

    500

    数据范围和注释 Hint

    【样例说明】
        采取下面的方案可以使每次领到的工资不会多于500。这个答案不能再少了。
    100 400   300 100   500   101   400   每一天的薪水
    <------1 <-------2 <---3 <---4 <---5  领取工资的时间
      500       400     500   101   400   领取到的工资

  • 相关阅读:
    Spring 学习笔记
    Hello Spring(3)ConnectionUtility
    android ndk开发
    java udp 广播及socket通讯
    android 横向滚动屏幕实现(2)
    android 基于ftp远程文件管理
    android 软键盘的弹出问题总结
    android 滚动字幕
    android 基于apache ftp server
    android 设置壁纸几种方法
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3942145.html
Copyright © 2020-2023  润新知