I.Array Division
数组分组,要求每组的和大于等于0,求最多可以分成几组。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 5010;
ll s[N];
int dp[N];
int a[N], b[N];
int main()
{
int T;
cin >> T;
while(T -- ) {
int n;
scanf("%d", &n);
memset(dp, 0, sizeof dp);
for(int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++ ) scanf("%d", &b[i]);
for(int i = 1; i <= n; i ++ ) a[i] = a[i] - b[i], s[i] = s[i - 1] + a[i];
for(int i = 1; i <= n; i ++ )
for(int j = 1; j <= i; j ++ )
if(s[i] - s[j - 1] >= 0 && s[j - 1] >= 0)
dp[i] = max(dp[i], dp[j - 1] + 1);
if(s[n] < 0) puts("-1");
else cout << dp[n] << endl;
}
return 0;
}
状态转移方程:
dp[i] = max(dp[i], dp[1 ~ i])
dp(i)表示到第i个点时最大分组。
注意判断可以分组的条件是dp(i)前面的分组是合法的,即s[i]
≥
\geq
≥ 0。
L.Monster Tower
模拟打怪兽
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 2e5 + 10;
int a[N];
priority_queue<int, vector<int>, greater<int> > q;
int main()
{
int T;
cin >> T;
while(T -- )
{
int n, k;
ll ans = 0, sum = 0;
cin >> n >> k;
for(int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
for(int i = 1; i <= n; i ++ ) {
q.push(a[i]);
if(q.size() == k) {
if(q.top() > sum + ans) {
ans = max(ans, q.top() - sum);
sum += q.top();
q.pop();
}
else {
sum += q.top();
q.pop();
}
}
}
while(q.size()) {
if(q.top() > sum + ans) {
ans = max(ans, q.top() - sum);
sum += q.top();
q.pop();
}
else {
sum += q.top();
q.pop();
}
}
cout << ans << endl;
}
return 0;
}
优先队列维护可以选的k层塔。
F.Sum of Numerators
给两个整数n和k,求
1
2
k
+
2
2
k
+
.
.
.
+
n
2
k
\frac{1}{2^k} +\frac{2}{2^k} + ...+\frac{n}{2^k}
2k1+2k2+...+2kn约分后的分子和。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
int main()
{
int T;
cin >> T;
while(T--)
{
LL n, k;
cin >> n >> k;
LL sum = (1 + n) * n / 2;
while(n && k)
{
k -- ;
n /= 2;
sum -= (1 + n) * n / 2;
}
cout << sum << endl;
}
return 0;
}
分子从1到n,只要看约分对一些数的影响。