Educational Codeforces Round 167 (Rated for Div. 2)
D. Smithing Skill (D)
很無語的一題······ 運用類似單調佇列思維處理出最優的選擇序列,之後發現 \(c_i\leq 10^9\) 沒法預處理,二分查詢又會被卡成 \(n^2\log n\),唯獨沒想到在 \(a_i\) 的 \(10^6\) 範圍內預處理()不好評價。
bool cmp(xxx n, xxx m) {
if(n.a - n.b != m.a - m.b) {
return n.a - n.b < m.a - m.b;
}
return n.a < m.a;
}
int main() {
// ...
sort(x + 1, x + n + 1, cmp);
x[0] = ans[0] = {INF, INF + 1};
for(int i = 1; i <= n; i++) {
if(x[i].a - x[i].b != x[i - 1].a - x[i - 1].b) {
if(x[i].a < ans[cnt].a) ans[++cnt] = x[i];
}
}
int cur = cnt;
for(int i = ans[cnt].a; i < N; i++) {
if(i >= ans[cur - 1].a) cur--;
if(!cur) break;
int num = (i - ans[cur].a) / (ans[cur].a - ans[cur].b) + 1;
int x = i - num * (ans[cur].a - ans[cur].b);
dp[i] = num * 2 + dp[x];
}
ll sum = 0;
for(int i = 1; i <= m; i++) {
scanf("%d", &c[i]);
if(c[i] < ans[1].a) sum += dp[c[i]];
else {
int num = (c[i] - ans[1].a) / (ans[1].a - ans[1].b) + 1;
int x = c[i] - num * (ans[1].a - ans[1].b);
sum += dp[x] + num * 2;
}
}
E. Distance to Different (E)
不同的 \(a\) 序列可能產生相同的 \(b\) 序列,因此只需要考慮可能的合法 \(b\) 序列;\(a\) 中連續 \(x\) 個相同的數會在 \(b\) 中產生一段長度為 \(x\) 的特定序列,題目即等價於將 \(b\) 劃分成至少 \(k\) 個不同的序列。對於除2以外的所有 \(x\),其產生的序列具有特異性,但 \(x = 2\) 時,若該序列位於 \(b\) 的中部,則 \(b = 1\),與 \(x = 1\) 情況相同,計算時應注意捨去。設 \(dp_{i, j}\) 表示將前 \(i\) 個數劃分成 \(j\) 個序列的方案數,特別地,為節省空間,\(j = k\) 時表示劃分出至少 \(k\) 個序列的方案數。使用字首和最佳化轉移,複雜度 \(O(nk)\).
dp[0][0] = 1;
sum[0] = 1; // 初始化
for(int i = 1; i <= n; i++) {
for(int j = 0; j <= k; j++) {
dp[i][min(j + 1, k)] += sum[j];
if(i > 2 && i < n) {
dp[i][min(j + 1, k)] += (mo - dp[i - 2][j]);
}
dp[i][min(j + 1, k)] %= mo;
}
for(int j = 1; j <= k; j++) {
sum[j] += dp[i][j];
sum[j] %= mo;
}
}