zoukankan      html  css  js  c++  java
  • P1182 数列分段`Section II` P1316 丢瓶盖 二分答案

    题目描述

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

    关于最大值最小:

    例如一数列4 2 4 5 142451要分成33段

    将其如下分段:

    [4 2][4 5][1][42][45][1]

    第一段和为66,第22段和为99,第33段和为11,和最大值为99。

    将其如下分段:

    [4][2 4][5 1][4][24][51]

    第一段和为44,第22段和为66,第33段和为66,和最大值为66。

    并且无论如何分段,最大值不会小于66。

    所以可以得到要将数列4 2 4 5 142451要分成33段,每段和的最大值最小为66。

    输入输出格式

    输入格式:

    11行包含两个正整数N,M。

    22行包含NN个空格隔开的非负整数A_iAi,含义如题目所述。

    输出格式:

    一个正整数,即每段和最大值最小为多少。

    输入输出样例

    输入样例#1: 复制
    5 3
    4 2 4 5 1
    输出样例#1: 复制
    6

    说明

    对于20\%20%的数据,有N≤10N10;

    对于40\%40%的数据,有N≤1000N1000;

    对于100\%100%的数据,有N≤100000,M≤N, A_iN100000,MN,Ai之和不超过10^9109。

    题目都很水

    规范二分写法!!!

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define LL long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 214748347
    #define N 100005
    int a[N];
    
    int main()
    {
        int n,k;
        RII(n,k);
        int R=0;
        int L=0;
        rep(i,1,n)
        {
            RI(a[i]);R+=a[i];
            L=max(L,a[i]);
        }
        while(L<R)
        {
            int mid=(L+R)>>1;
    
            int cnt=0;
            int temp=0;
            rep(i,1,n)
            {
                temp+=a[i];
                if(temp>mid)
                    cnt++,temp=a[i];
            }
            if(temp)cnt++;
    
            if(cnt>k)L=mid+1;
            else R=mid;//答案求的是最小值  所以当有=时右往左靠
        }
        cout<<L;
        return 0;
    }
    View Code

    题目描述

    陶陶是个贪玩的孩子,他在地上丢了A个瓶盖,为了简化问题,我们可以当作这A个瓶盖丢在一条直线上,现在他想从这些瓶盖里找出B个,使得距离最近的2个距离最大,他想知道,最大可以到多少呢?

    输入输出格式

    输入格式:

    第一行,两个整数,A,B。(B<=A<=100000)

    第二行,A个整数,分别为这A个瓶盖坐标。

    输出格式:

    仅一个整数,为所求答案。

    输入输出样例

    输入样例#1: 复制
    5 3
    1 2 3 4 5
    
    输出样例#1: 复制
    2


    二分答案 最好的方法!!!!!!!
    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 214748347
    #define N 100005
    ll a[N];
    int n,k;
    bool check(ll x)//x为最近距离
    {
        int cnt=1;
        int temp=1;
        rep(i,2,n)
        {
            if(a[i]-a[temp]>=x)
                cnt++,temp=i;
        }
        return cnt>=k;
    }
    int main()
    {
       RII(n,k);
       rep(i,1,n)
          cin>>a[i];
    
       sort(a+1,a+1+n);
       ll R=a[n]-a[1];
       ll L=0;
       ll ans=0;
       while(L<=R)
       {
           ll mid=(L+R)>>1;
           if(check(mid))L=mid+1,ans=max(ans,mid);
           else  R=mid-1;
       }
       cout<<L-1;
       return 0;
    }
    View Code

    其他写法:

    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 214748347
    #define N 100005
    ll a[N];
    int n,k;
    bool check(ll x)//x为最近距离
    {
        int cnt=1;
        int temp=1;
        rep(i,2,n)
        {
            if(a[i]-a[temp]>=x)
                cnt++,temp=i;
        }
        return cnt>=k;
    }
    int main()
    {
       RII(n,k);
       rep(i,1,n)
          cin>>a[i];
    
       sort(a+1,a+1+n);
       ll R=a[n]-a[1];
       ll L=0;
       ll ans=0;
       while(L<R)
       {
           ll mid=(L+R+1)>>1;
           if(check(mid))L=mid;
           else  R=mid-1;
       }
       cout<<L;
       return 0;
    }
    View Code
    #include<bits/stdc++.h>
    using namespace std;
    //input by bxd
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define repp(i,a,b) for(int i=(a);i>=(b);i--)
    #define RI(n) scanf("%d",&(n))
    #define RII(n,m) scanf("%d%d",&n,&m)
    #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
    #define RS(s) scanf("%s",s);
    #define ll long long
    #define REP(i,N)  for(int i=0;i<(N);i++)
    #define CLR(A,v)  memset(A,v,sizeof A)
    //////////////////////////////////
    #define inf 214748347
    #define N 100005
    ll a[N];
    int n,k;
    bool check(ll x)//x为最近距离
    {
        int cnt=1;
        int temp=1;
        rep(i,2,n)
        {
            if(a[i]-a[temp]>=x)
                cnt++,temp=i;
        }
        return cnt>=k;
    }
    int main()
    {
       RII(n,k);
       rep(i,1,n)
          cin>>a[i];
    
       sort(a+1,a+1+n);
       ll R=a[n]-a[1];
       ll L=0;
       ll ans=0;
       while(L<=R)
       {
           ll mid=(L+R)>>1;
           if(check(mid))L=mid+1;
           else  R=mid-1;
       }
       cout<<L-1;
       return 0;
    }
    View Code
  • 相关阅读:
    SQL: 从一个表随机读取一行或几行记录的问题
    Android: 创建一个AlertDialog对话框,必须按确定或取消按钮才能关闭对话框,禁止按[返回键]或[搜索键]关闭
    Asp: 解决脚本输出网页出现乱码情况
    Java: |(或运算) 与 多选判断
    ASP: Response 对象 错误 'ASP 0251 : 80004005' 解决办法
    Java: 在dos窗口输入密码,不要把密码直接显示出来,原来可以这么简单
    Android: 网络随时需要在3G和Wifi切换,网络程序需要注意
    Android: 待机时如何让程序继续运行 extends Service
    Android: View换切后,无法正常设置焦点或切换后TextView的虚拟键盘不弹出
    MySQL存储过程学习笔记
  • 原文地址:https://www.cnblogs.com/bxd123/p/10691843.html
Copyright © 2011-2022 走看看