Nanami and Arithmetic Sequence
题面
思路
炸鱼题
只有n=1的时候,只有一个等差数列;
其余时候,都是都有无数个等差数列。
代码
#include <iostream>
using namespace std;
int main() {
int t, n;
cin >> t;
while (t--) {
cin >> n;
if (n == 1)
cout << "1\n";
else
cout << "-1\n";
}
return 0;
}
珠宝价值
题面
思路
浓缩一下,题目是在求数组的连续子数组最大和。
即一个很经典的问题——最大子段和。
这题在洛谷上也有,链接在下,感兴趣的朋友可以一试。(注意数据范围的区别)
最大子段和 - 洛谷
本题采用动态规划来解
设dp[i]表示[0,i]闭区间以i为右边界的最大子段和(我们并不关注左边界的位置)
最开始有dp[0] = v[0]
由[0,i]推[0,i+1]时,如果dp[i]+v[i+1]>dp[i],则说明加上该值后总和变大,所以需dp[i+1]=dp[i]+v[i+1]。否则,从头开始计和,dp[i+1]=v[i+1]。
最后找到dp数组中的最大值即可
代码
#include <iostream>
using namespace std;
#define MAXN 10005
int v[MAXN];
int dp[MAXN];
int main() {
int n;
cin >> n;
int i = 0;
while (n--) {
cin >> v[i];
i++;
}
dp[0] = v[0];
for (int j = 0; j < i - 1; j++) {
if (dp[j] + v[j + 1] > v[j + 1]) {//条件里也可以是dp[j]>0
dp[j + 1] = dp[j] + v[j + 1];
} else {
dp[j + 1] = v[j + 1];
}
}
int maxv = -1e9;
for (int j = 0; j < i; j++) {
if (dp[j] > maxv)
maxv = dp[j];
}
cout << maxv << endl;
return 0;
}
Nanami and Toys Buying Problem
题面
思路
每个a[i]最多只被取一次,最多只有一个b[i]会被取2次以上。
枚举被多次取的玩具,设当前取的为b[i],那么对于行a来说,a[j]>b[i]时才有取的必要,否则不用取。(当j<i时,需要先取出a[i]才能取b[i])
可以按a的大小排序,枚举b,结合二分查找得到j。
代码
先放一份能反映基础思路,但TLE了的代码
#include <iostream>
using namespace std;
const int maxn = 2e5 + 5;
int a[maxn], b[maxn];
int main() {
int t;
cin >> t;
while (t--) {
int n, k;
cin >> n >> k;
int k2 = k;
long long ans = 0;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
cin >> b[i];
int i, j;
for (i = 0; i < n - 1; i++)
for (j = 0; j < n - 1 - i; j++)
if (a[j] < a[j + 1]) {
swap(a[j], a[j + 1]);
swap(b[j], b[j + 1]);
}
for (int i = 0; i < n; i++) {
k = k2;
long long currentans = 0;
if (k >= 1) {
currentans += a[i];
k--;
}
int maxj = -1;
for (int j = 0; j < n; j++) {
if (j != i) {
if (a[j] > b[i] && k > 0) {
currentans += a[j];
k--;
maxj = j;
}
} else
continue;
}
if (k > 0)
currentans += 1ll * k * b[i];
if (currentans > ans)
ans = currentans;
}
cout << ans << endl;
}
return 0;
}
再放一份优化过的代码,使用二分+前缀和
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 5;
int T, n, k;
int a[maxn], b[maxn], s[maxn];
long long preSum[maxn];
long long spe1()
{
sort(a + 1, a + n + 1);
return a[n];
}
long long ans, sum;
int main()
{
cin >> T;
for (int rt = 1; rt <= T; rt++)
{
ans = 0;
cin >> n >> k;
for (int i = 1; i <= n; i++) {cin >> a[i]; s[i] = a[i];}
for (int i = 1; i <= n; i++) cin >> b[i];
if (k == 0)
{
cout << 0 << '\n';
continue;
}
if (k == 1)
{
cout << spe1() << '\n';
continue;
}
sort(s + 1, s + n + 1);
for (int i = 1; i <= n; i++) preSum[i] = preSum[i - 1] + s[i];
int res = k - 1;
for (int i = 1; i <= n; i++)
{
sum = a[i];
//cout << sum << '\n';
int num = n + 1 - (upper_bound(s + 1, s + n + 1, b[i]) - s);
if (a[i] <= b[i])
{
if (res <= num) sum += preSum[n] - preSum[n - res];
else sum += preSum[n] - preSum[n - num] + 1ll * (res - num) * b[i];
} else {
if (res < num - 1)
{
int lowPos = lower_bound(s + 1, s + n + 1, a[i]) - s;
if (a[i] >= s[n - res + 1] && lowPos >= n - res + 1)
{
sum += preSum[n] - preSum[n - res - 1] - a[i];
}
else {
sum += preSum[n] - preSum[n - res];
}
}
else sum += preSum[n] - preSum[n - num] - a[i] + 1ll * (res - (num - 1)) * b[i];
}
ans = max(ans, sum);
//cout << sum << '\n' << '\n';
}
cout << ans << '\n';
}
return 0;
}
类似题目(某厂面试题)