requests介面測試-headers
前言
只做了 A、B、C 三題。= =,D 的 dp 沒寫出來,貪了好久。
A. Bad Triangle
題目大意
在給定 \(n\) 個數裡選擇出三個數,使得其不能組成三角形
分析
三角形的組成條件為任意兩邊和大於第三邊。不妨把 \(n\) 個數按照升序排列(題目預設升序),然後取前面最小的兩個為兩個邊,計算它們的和。再從第三個開始找,找到大於等於和的邊就是答案。找不到就輸出 \(-1\) 。
程式碼
#include <bits/stdc++.h> #define lowbit(x) ((x)&(-x)) #define mem(i, a) memset(i, a, sizeof(i)) #define sqr(x) ((x)*(x)) #define ls(x) (x << 1) #define rs(x) (x << 1 | 1) typedef long long ll; const double eps = 1e-8; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; const int maxn = 1e5 + 7; using namespace std; int arr[maxn]; int main(void){ #ifdef ljxtt freopen("data.in", "r", stdin); #endif int T; scanf("%d", &T); while(T--){ int n; scanf("%d", &n); for(int i = 0; i < n; i++) scanf("%d", &arr[i]); int sum = arr[0] + arr[1]; int inx = -1; for(int i = 2; i < n; i++){ if(arr[i] >= sum){ inx = i; break; } } if(inx == -1) puts("-1"); else printf("1 2 %d\n", inx + 1); } return 0; }
B. Substring Removal Game
題目大意
A 和 B兩個人玩遊戲,A先行。
遊戲規則為:給一段 01 串,每次操作都可以將一段連續相同的字元去掉,所得到的分數為去掉1的個數。當字串為空時停止遊戲。
A、B兩人都按照對自己最優的策略走,問A能得到的最大的分數是多少。
分析
顯然,去掉一段相同的 0 並沒有什麼卵用。所以,貪心地取連續最長的 1 即可。
程式碼
#include <bits/stdc++.h> #define lowbit(x) ((x)&(-x)) #define mem(i, a) memset(i, a, sizeof(i)) #define sqr(x) ((x)*(x)) #define ls(x) (x << 1) #define rs(x) (x << 1 | 1) typedef long long ll; const double eps = 1e-8; const double pi = acos(-1.0); const int inf = 0x3f3f3f3f; const int maxn = 1e5 + 7; using namespace std; char s[maxn]; vector<int> arr; int main(void){ #ifdef ljxtt freopen("data.in", "r", stdin); #endif int T; scanf("%d", &T); while(T--){ scanf("%s", s); int len = strlen(s), cnt = 0; for(int i = 0; i < len; i++){ if(s[i] == '1'){ cnt++; }else{ if(cnt != 0) arr.push_back(cnt); cnt = 0; } } if(cnt != 0) arr.push_back(cnt); sort(arr.begin(), arr.end(), greater<int> ()); int ans = 0; for(int i = 0; i < arr.size(); i += 2) ans += arr[i]; printf("%d\n", ans); arr.clear(); } return 0; }
C. Good Subarrays
題目大意
給定一個序列,詢問有多少個區間滿足:
\[\sum_{i = l}^{r}a_i = r - l + 1 \]
分析
用字首和表示上式為:
\[\begin{aligned} S(r) - S(l - 1) &= r - l + 1 \\ S(r) - r &= S(l - 1) - (l - 1)\\ f(r) &= f(l - 1) \end{aligned} \]
其中 \(f(x) = S(x) - x\),且 \(f(0) = 0\)。
所以,也就是在所有的 \(f(x)\) 裡任意取出兩個相同的數字,詢問方案數。
統計一下相同數字的個數,用組合數算一下 \(C_n^2\)
程式碼
#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
#define mem(i, a) memset(i, a, sizeof(i))
#define sqr(x) ((x)*(x))
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
typedef long long ll;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 7;
using namespace std;
ll arr[maxn];
map<ll, int> ma;
int main(void){
#ifdef ljxtt
freopen("data.in", "r", stdin);
#endif
int T; scanf("%d", &T);
while(T--){
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%1lld", &arr[i]);
for(int i = 1; i <= n; i++) arr[i] += arr[i - 1];
for(int i = 1; i <= n; i++) arr[i] -= i;
for(int i = 0; i <= n; i++) ma[arr[i]]++;
ll ans = 0;
for(auto it: ma){
if(it.second > 1) ans += 1ll * it.second * (it.second - 1) / 2;
}
printf("%lld\n", ans);
ma.clear();
}
return 0;
}
D. Colored Rectangles
題目大意
給定 R、G、B對的紅色、綠色、藍色的木棒,對應顏色的第 i 對的長度為 ri,gi,bi。你可以進行如下操作:
在兩種不同的顏色裡各選出一對,使得它們組成一個長方形,並將矩形的面積加入到答案裡。
題目要求使得最後的答案最大。
分析
這種題目要麼貪心,要麼dp。
很顯然有個貪心的想法,就是把三種木棒混合在一起,按長度排序。然後從大到小列舉木棍,再在剩下的木棍裡選出顏色不同但最大的木棍組成矩形,加入到答案裡。列舉一遍就是答案。但這樣有一個問題就是下面這樣一個樣例:
1 1 2
1
1
1 1
上面這個樣例就有可能使得 R 和 G 配對,然後剩下的兩個 B 沒辦法配對。最優的答案是 R 和 B 配對,G 和 B 配對。所以上面這個貪心不成立。
所以我們考慮一下dp。先把三種不同的木棍按長度降序排列,定義 \(dp[i][j][k]\) 為 R、G、B分別用了 i,j,k 個木棍所取得的最大答案,那麼就有轉移方程為:
\[\begin{array} \\ dp[i][j][k] = \max(&dp[i - 1][j - 1][k] + R[i]\times G[i], \\ &dp[i - 1][j][k - 1] + R[i] \times B[i], \\&dp[i][j - 1][k - 1] + G[i] \times B[i]) \end{array} \]
初值為 \(dp[0][0][0] = 0\) 。
程式碼
#include <bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
#define mem(i, a) memset(i, a, sizeof(i))
#define sqr(x) ((x)*(x))
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
typedef long long ll;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int maxn = 2e2 + 7;
using namespace std;
ll dp[maxn][maxn][maxn];
int arr[3][maxn];
int main(void){
#ifdef ljxtt
freopen("data.in", "r", stdin);
#endif
int num[3]; for(int i = 0; i < 3; i++) scanf("%d", &num[i]);
for(int i = 0; i < 3; i++){
for(int j = 0; j < num[i]; j++)
scanf("%d", &arr[i][j]);
sort(arr[i], arr[i] + num[i], greater<int> ());
}
ll ans = 0;
for(int i = 0; i <= num[0]; i++)
for(int j = 0; j <= num[1]; j++)
for(int k = 0; k <= num[2]; k++){
dp[i + 1][j + 1][k] = max(dp[i + 1][j + 1][k], dp[i][j][k] + 1ll * arr[0][i] * arr[1][j]);
dp[i + 1][j][k + 1] = max(dp[i + 1][j][k + 1], dp[i][j][k] + 1ll * arr[0][i] * arr[2][k]);
dp[i][j + 1][k + 1] = max(dp[i][j + 1][k + 1], dp[i][j][k] + 1ll * arr[1][j] * arr[2][k]);
ans = max(ans, dp[i][j][k]);
}
printf("%lld\n", ans);
return 0;
}