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

题目

思路:

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

#include 
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> 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;
}

你可能感兴趣的:(codeforces,算法)