题意: 给定长度为n的数组,给定n个数字,a[i] <= a[i + 1], 问是否可以找到ai,aj,ak,使得这三个数字组不成三角形。
题解: 一开始看错题意,找三角形,写了半个小时发现要找不能作三角形的。只要判断前两个数字和最后一个数字便可。由于前两个数字最小,最后一个数字最大。
代码:c++
#include <bits/stdc++.h> using namespace std; int const N = 1e5 + 10; int a[N], n, T; int main() { cin >> T; while (T--) { cin >> n; for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); if (a[1] + a[2] <= a[n]) cout << 1 << " " << 2 << " " << n << endl; else cout << -1 << endl; } return 0; }
题意: 给你一个长度为n的0,1字符串,两我的轮流选择其中很多于一位的连续子序列,得分为所选子序列中1个数的总和,你先选,问最多可以得到多少分。
题解: 把连续的1分段拿出来,排序完倒叙,奇数和累加就是得分
代码:数组
#include <bits/stdc++.h> using namespace std; int const N = 1e5 + 10; int a[N], n, T; int main() { cin >> T; while (T--) { string s; cin >> s; vector<int> cnt; int l = 0, r = 0; while (s[r] == '0' && r < s.size()) r++; // cout << r << endl; l = r; // cout << l << " " << r << endl; while (1) { while (s[r] == '1' && r < s.size()) r++; // cout << r << endl; cnt.push_back(r - l); while (s[r] == '0' && r < s.size()) r++; l = r; if (r == s.size()) break; } int res = 0; sort(cnt.begin(), cnt.end()); reverse(cnt.begin(), cnt.end()); for (int i = 0; i < cnt.size(); ++i) { if (i % 2 == 0) { res += cnt[i]; } } cout << res << endl; } return 0; }
题意: 给你T组数据,每组给你一个长度为n的字符串,求知足
\(\sum_{i=l}^{r}ai=r-l+1\) 的子区间的个数(i < j)
题解: 把\(\sum_{i=l}^{r}ai=r-l+1\)左右两边都减去r-l+1,则得\(\sum_{i=l}^{r}(ai-1)=0\),因此只须要找区间和为0得个数。找区间和为0得个数能够使用前缀统计的方式,具体见代码。
代码:spa
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 1e5 + 10; LL T, n, a[N], sum[N]; string s; map<LL, LL> mp; int main() { cin >> T; while (T--) { cin >> n; cin >> s; mp.clear(); for (int i = 0; i < s.size(); ++i) a[i + 1] = s[i] - '0' - 1; for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i]; // for (int i = 1; i <= n; ++i) cout << a[i] << endl; LL res = 0; // int l = 1; mp[0]++; // while (a[l] == 0 && l < n) res ++, l ++; for (int i = 1; i <= n; ++i) { // if (a[i] == 0) res++; res += mp[sum[i]]; mp[sum[i]]++; } cout << res << endl; } } // 1 2 0 // 0 1 -1 // 1 + // 0 0 0 // 11011 // 0 0 -1 0 0 // 1 + 1 + 1 + 1 +
题意: 有R,G,B三种颜色的棍子。如今告诉你每种棍子长度的对数和每对的长度,让你用两种不一样颜色的棍子对围成矩形,求每一个矩形加起来的最大值
题解: 把每一个棍子拿起来从大到小排序,而后dp暴力转移
代码:.net
#include <bits/stdc++.h> using namespace std; typedef long long LL; int const N = 210; LL f[N][N][N], r, g, b, A[N], B[N], C[N]; int main() { cin >> r >> g >> b; memset(f, 0, sizeof f); for (int i = 1; i <= r; ++i) scanf("%lld", &A[i]); for (int i = 1; i <= g; ++i) scanf("%lld", &B[i]); for (int i = 1; i <= b; ++i) scanf("%lld", &C[i]); sort(A + 1, A + r + 1); reverse(A + 1, A + r + 1); sort(B + 1, B + g + 1); reverse(B + 1, B + g + 1); sort(C + 1, C + b + 1); reverse(C + 1, C + b + 1); for (int i = 0; i <= r; ++i) { for (int j = 0; j <= g; ++j) { for (int k = 0; k <= b; ++k) { LL t1 = 0 , t2 = 0, t3 = 0; if (i && j) t1 = f[i - 1][j - 1][k] + A[i] * B[j]; if (i && k) t2 = f[i - 1][j][k - 1] + A[i] * C[k]; if (j && k) t3 = f[i][j - 1][k - 1] + B[j] * C[k]; f[i][j][k] = max(max(t1, f[i][j][k]), max(t2, t3)); } } } LL res = 0; for (int i = 0; i <= r; ++i) for (int j = 0; j <= g; ++j) for (int k = 0; k <= b; ++k) res = max(res, f[i][j][k]); cout << res << endl; return 0; }