题解
最大值最小化,想到了二分
而对于一个二分到的 \(\mathscr{maxlen}\) 而言,如何判断是否存在一种分法使得最大值不大于它?
对于一个给定的二分值而言,要想成功有两个约束条件,一个是间断值不超过 \(\mathscr{maxlen}\) ,一个是选中值之和不超过 \(\mathscr{maxlen}\)
由此我们让第一个条件作为约束条件来寻找第二个条件是否成立
这里太巧妙了!!!!
设 \(dp[i]\) 为选中 \(i\) ,且 \(i\) 之前的间断值都不超过 \(maxlen\) 的最小值
\(dp[i]\) 是由前面间断值不大于 \(maxlen\) 的最小的 \(dp[i]\) 转移而来的
然后判断 \(dp[n+1]\) 有没有大于 \(maxlen\)
真的太巧妙了!!!
code
···
include<bits/stdc++.h>
define ll long long
using namespace std;
ll n;
ll a[100005]={0};
ll pres[100005]={0};
ll dp[100005]={0};
struct node
{
ll x;
bool operator<(const node &b) const{return dp[x]>dp[b.x];}
};
ll check(ll maxlen)
{
priority_queue<node> q;
q.push({0});
a[n+1]=0;
for(ll i=1;i<=n+1;i++)
{
while(q.size()&&pres[i-1]-pres[q.top().x]>maxlen) q.pop();
ll x=q.top().x;
dp[i]=dp[x]+a[i];
q.push({i});
}
if(dp[n+1]>maxlen) return 0;
return 1;
}
int main()
{
ll t;
cin>>t;
while(t--)
{
cin>>n;
for(ll i=1;i<=n;i++)
{
cin>>a[i];
pres[i]=pres[i-1]+a[i];
}
ll l=0,r=pres[n];
while(l+1<r)
{
ll mid=(l+r)/2;
if(check(mid))r=mid;
else l=mid;
}
cout<<r<<endl;
}
return 0;
}
···
标签:Elements,ll,cin,100005,maxlen,pres,Blocking,dp From: https://www.cnblogs.com/pure4knowledge/p/18075777