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";elsecout << "-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 10005int 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]>0dp[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;}} elsecontinue;}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;
}
类似题目(某厂面试题)