uva 714

来源:互联网 发布:淘宝男童运动套装 编辑:程序博客网 时间:2024/06/06 18:45

题意:

          把一个包含m个正整数的序列划分成k个非空的连续子序列,使得每个正整数恰好属于一个序列。

题解:

         最大值尽量小是一种很常见的优化目标。二分法,right=序列总和,left=序列中的最大数。判断是否小于等于K个分发,否则left=mid+1,一直二分直至求到最小的最大值。

代码:

         

#include <iostream>#include <cstring>using namespace std;typedef long long LL;const int maxn = 500+5;int vis[maxn];LL m,k,data[maxn],l,r;bool solve(LL sum){    int count=0;    LL s =0 ;    //cout<<sum<<" ";    for(int i=1;i<=m;i++)    {        if(s+data[i]<=sum)            s+=data[i];        else{            s=data[i];            count++;        }    }    count++;    //cout<<count<<endl;    if(count>k) return false;    return true;}void output(){    memset(vis,0,sizeof(vis));    int count=1;    LL sum=0;    for(int i=m;i>=1;i--)    {        if(sum+data[i] <= l)            sum += data[i];        else{            count++;            sum =data[i];            vis[i]=1;            //cout<<i<<" "<<count<<endl;        }    }    for(int i=1;i<=m&&count<k;i++)    {        if(!vis[i])        {            vis[i]=1;            count++;        }    }    for(int i=1;i<m;i++)    {        cout<<data[i]<<" ";        if(vis[i]) cout<<"/ ";    }    cout<<data[m]<<endl;}int main(){    int T;    cin>>T;    while(T--)    {        cin>>m>>k;        l=0,r=0;        for(int i=1;i<=m;i++){            cin>>data[i];            r+=data[i];            l = max(l,data[i]);        }        while(r>=l)        {            LL mid = (r+l)>>1;            if(solve(mid)) {r=mid-1;}            else l=mid+1;        }        output();    }    return 0;}