Codeforces 1700D. River Locks

传送门
\(\texttt{Difficulty:1900}\)

题目大意

\(n(1\le n\le2\cdot10^5)\) 各容积为 \(v_i(1\le v_i\le10^9)\) 的水槽,每个水槽上方有一个水龙头,每分钟流出的水为 \(1\) ,一个水槽 \(i\) 满了之后,水会继续流向下一个水槽(即使 \(v_i+1>v_i\) )。最后一个水槽满了后多的水会留走, \(q(1\le q\le2\cdot10^5)\) 次询问,每次询问 \(t(1\le t\le10^9)\) ,求要在 \(t\) 分钟内填满所有水槽至少要打开几个水龙头,无法做到输出 \(-1\)

思路

考虑水龙头应当从左至右依次打开,这样从最后一个水槽流出去浪费的水会最少,因为水只能向右流,因此如果存在一个前缀,其所有水龙头都打开仍不能在 \(t\) 内填满该前缀,则输出 \(-1\) ,即是否无解只需判断是否存在一个 \(i\) ,满足 \(it<\sum_{j=1}^iv_j\) , 即 \(t<\lceil\frac{\sum_{j=1}^iv_j}{i}\rceil\) 。于是只需找 \(\lceil\frac{\sum_{j=1}^iv_j}{i}\rceil\) 最大的来判断即可。对于有解,任何一个前缀开满水龙头后都能填满该前缀,只需让多出来的能继续填满后面即可,答案显然为 \(\lceil\frac{\sum_{i=1}^nv_i}{t}\rceil\) 。复杂度 \(O(n)\)

代码

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using LD = long double;
using ULL = unsigned long long;
using PII = pair<int, int>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mst(x,v) memset(x,v,sizeof(x))
#define mk make_pair
#define int LL
//#define lc P*2
//#define rc P*2+1
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const LL MOD = 1000000009;
const LL mod = 998244353;
const int maxn = 200010;

LL T, N, Q, A[maxn], S[maxn];

void solve()
{
	LL mx = -INF;
	for (int i = 1; i <= N; i++)
		S[i] = S[i - 1] + A[i], mx = max(mx, (S[i] + i - 1) / i);
	while (Q--)
	{
		cin >> T;
		if (T < mx)
			cout << -1 << endl;
		else
			cout << (S[N] + T - 1) / T << endl;
	}
}

signed main()
{
	IOS;
	cin >> N;
	for (int i = 1; i <= N; i++)
		cin >> A[i];
	cin >> Q;
	solve();

	return 0;
}
posted @ 2022-06-30 22:14  Prgl  阅读(50)  评论(0)    收藏  举报