给定长度为n的数组a,若在p1,p2,...,p[m]位置阻塞,代价为max(sum(1, p[1]-1), sum(p[1]+1,p[2]-1),...,a[p1]+...+a[pm]),求最小代价

题目

思路:

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define pb push_back
#define fi first
#define se second
#define lson p << 1
#define rson p << 1 | 1
const int maxn = 1e6 + 5, inf = 1e18, maxm = 4e4 + 5, mod = 1e9 + 7, N = 1e6;
int a[maxn], b[maxn];
// bool vis[maxn];
int n, m;
string s;
int pre[maxn];
int f[maxn];

bool check(int x){
	for(int i = 1; i <= n; i++){
		f[i] = inf;
	}
	int j = 0;
	int sum = a[1];
	set<pair<int, int>> S;
	f[1] = a[1];
	f[0] = 0;
	S.insert({f[0], 0});//设置虚拟点,方便后续状态转移
	S.insert({f[1], 1});
	for(int i = 2; i <= n; i++){
		while(j + 1 < i && sum > x){
			sum -= a[j + 1];
			S.erase({f[j], j});
			j++;
		}
		
		if(!S.empty()){
			auto pr = *S.begin();
			f[i] = pr.first + a[i];
		}
		// cout << i << ' ' << j << ' ' << sum << ' ' << f[i] << '\n';
		sum += a[i];
		S.insert({f[i], i});
	}
	int mn = inf;
	for(int i = 0; i <= n; i++){
		if(f[i] <= x && pre[n] - pre[i] <= x){
			return 1;
		}
	}
	return 0;
}
void solve(){
    int res = 0;
    int k;
    int x;
    int q;
    cin >> n;
	for(int i = 1; i <= n; i++){
		cin >> a[i];
		pre[i] = pre[i - 1] + a[i];
	}
	int l = 1, r = inf;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(check(mid)) r = mid - 1;
		else l = mid + 1;
	}
	cout << l << '\n';
	// cout << check(7) << '\n';
}
    
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T = 1;
    cin >> T;
    while (T--)
    {
        solve();
    }
    return 0;
}

  • 14
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__night_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值