题目链接:https://www.luogu.com.cn/problem/P1281
描述:
分析:给一个数组ai,要求划分为k个部分.
最小化每个部分和的最大值
若有多解,尽量让前边的组划分的数目尽量小.
最小化最大值,经典二分问题,二分出最小的每个组别最大值后,考虑构造答案.
由于要前面的人尽量少抄,考虑从后边往前面构造即可.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5+2;
const int INF = 1e9+7;
typedef pair<int,int> pii;
int a[maxn];int n,k;
bool check(int K){
int now = 0;int cnt = 1;
for(int i=1;i<=n;i++){
if(a[i]>K){
return false;
}
if(now+a[i]<=K){
now+=a[i];
}
else now=a[i],cnt++;
}
return cnt<=k;
}
int main(){
scanf("%d %d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
int L = 0,R=INF,ans;
while(L<=R){
int mid = (L+R)>>1;
if(check(mid)){
ans = mid,R = mid-1;
}
else L = mid + 1;
}
int now = 0;
vector<pii> path;
for(int i=n;i>=1;){
int t = i;
while(i>=1&&now+a[i]<=ans){
now+=a[i];i--;
}
if(i==0){
path.push_back({i+1,t});
break;
}
else path.push_back({i+1,t});
now = 0;
}
reverse(path.begin(),path.end());
for(auto x : path){
cout<<x.first<<" "<<x.second<<"\n";
}
return 0;}