inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
constint MAXN = 5e4 + 10;
int n, aa[MAXN];
boolcheck(int a, int b, int c){ return (1ll * aa[a] + 1ll * aa[b]) > (1ll * aa[c]); }
intmain(){ int T = read(); while (T --> 0) { n = read(); for (int i = 1; i <= n; ++i) aa[i] = read(); if (aa[n] >= aa[1] + aa[2]) printf("%d %d %d\n", 1, 2, n); elseputs("-1"); } return0; }
B. Substring Removal Game
解题思路
注意到如果 Alice 移除了一个 0 或者好几个 0 把两段 1 连了起来,那么 Bob 就可以直接获得这两段 1,这相当于给对手送分啊!
inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
constint MAXN = 200 + 10;
int rs, gs, bs; longlongint rr[MAXN], gg[MAXN], bb[MAXN]; longlongint dp[MAXN][MAXN][MAXN];
intmain(){ rs = read(); gs = read(); bs = read(); for (int i = 1; i <= rs; ++i) rr[i] = read(); for (int i = 1; i <= gs; ++i) gg[i] = read(); for (int i = 1; i <= bs; ++i) bb[i] = read(); std::sort(rr + 1, rr + 1 + rs, std::greater<longlongint>()); std::sort(gg + 1, gg + 1 + gs, std::greater<longlongint>()); std::sort(bb + 1, bb + 1 + bs, std::greater<longlongint>()); longlongint ans = 0; dp[1][1][0] = rr[1] * gg[1]; dp[1][0][1] = rr[1] * bb[1]; dp[0][1][1] = gg[1] * bb[1]; for (int i = 0; i <= rs; ++i) { for (int j = 0; j <= gs; ++j) { for (int k = 0; k <= bs; ++k) { dp[i][j][k] = std::max( std::max( (i && j ? dp[i - 1][j - 1][k] : 0) + rr[i] * gg[j], (i && k ? dp[i - 1][j][k - 1] : 0) + rr[i] * bb[k] ), std::max( (j && k ? dp[i][j - 1][k - 1] : 0) + gg[j] * bb[k], dp[i][j][k] ) ); ans = std::max(ans, dp[i][j][k]); } } } printf("%lld\n", ans); return0; }
inlineintread(){ int s = 0, x = 1; char ch = getchar(); while (!isdigit(ch)) { if (ch == '-') x = -x; ch = getchar(); } while (isdigit(ch)) { s = s * 10 + ch - '0'; ch = getchar(); } return s * x; }
constint FIR = 0; constint LIG = 1;
int n; longlongint sum, dbd; // sum 为伤害总和,dbd 为翻倍来的额外伤害 std::set<longlongint> fire, light; std::set<longlongint> doubled, nondbd;
voidinsert(int typ, longlongint pwr){ sum += pwr; if (typ == FIR) fire.insert(pwr); else light.insert(pwr); // 满足条件就往翻倍里面塞,大不了一会维护的时候再清出来 if (nondbd.empty() || (pwr > *nondbd.rbegin())) doubled.insert(pwr), dbd += pwr; else nondbd.insert(pwr); }
voiderase(int typ, longlongint pwr){ sum -= pwr; if (typ == FIR) fire.erase(pwr); else light.erase(pwr); if (doubled.count(pwr)) doubled.erase(pwr), dbd -= pwr; else nondbd.erase(pwr); }