看到区间操作就想到前缀和和差分。属于常用套路
#include <bits/stdc++.h>
using namespace std;
#include<stack>
#define int long long
signed main()
{
int t;
cin >> t;
for(int i = 0;i<t;i++)
{
int n;
cin >> n;
int a[n];
for(int k = 0;k<n;k++) cin>>a[k];
int ans = 0;
int temp = a[n - 1];
for(int k = n - 1;k>=1;k--)
{
if(a[k] - a[k - 1] >= 0) //后缀相减使其等于前缀
{
ans += (a[k] - a[k - 1]);
temp -= (a[k] - a[k - 1]);
}
else
{
ans += (a[k - 1] - a[k]);
}
}
cout << ans + abs(temp) << endl;
}
system("pause");
}
设 D P [ i ] DP[i] DP[i],处理到第i个lock,前i个lock全部开启,并装满前i个lock所需要的最短时间。guess:
所以
D
P
[
i
]
=
m
a
x
(
D
P
[
i
−
1
]
,
⌈
s
u
m
(
v
[
1
:
i
]
)
i
⌉
)
DP[i] = max(DP[i-1],\lceil \frac{sum(v[1:i])}{i}\rceil)
DP[i]=max(DP[i−1],⌈isum(v[1:i])⌉)
对每个query,必要条件是
t
q
u
e
r
y
>
=
d
p
[
n
]
t_{query} >= dp[n]
tquery>=dp[n].在这样的时间段内,若取q个管道,可保证有充足的时间将这前q个装满。
因此给定q,只需检查
t
q
u
e
r
y
⋅
q
≥
s
u
m
(
v
[
1
:
n
]
)
t_{query} \cdot q \geq sum(v[1:n])
tquery⋅q≥sum(v[1:n])是否满足即可。找到最小这样的q即可。
#include <bits/stdc++.h>
using namespace std;
#include<stack>
#define int long long
signed main()
{
int n;
cin >> n;
int v[n];
int prev[n + 1];
prev[0] = 0;
for(int i = 0;i<n;i++)
{
scanf("%ld",&v[i]);
prev[i + 1] = prev[i] + v[i];
}
int dp[n + 1];
dp[1] = v[0];
for(int i = 2;i<=n;i++) dp[i] = max(dp[i - 1],(long long)ceil((double)prev[i] / i));
int q;
cin >> q;
for(int i = 0;i<q;i++)
{
int t;
scanf("%ld",&t);
if(t < dp[n]) printf("-1\n");
else //找到第一个大于等于ceil(prev[n]/t)的prefixsum之和
{
t = (int)ceil((double)prev[n]/t);
printf("%ld\n",t);
}
}
system("pause");
}