「題解」Codeforces Round 894 (Div. 3)

A. Gift Carpet

Problem

題目

Sol & Code

簽到題

#include <bits/stdc++.h>
#define N 21

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n, m, a[4];
std::string s[N];

int main() {
  scanf("%d", &T);
  a[0] = 'v', a[1] = 'i', a[2] = 'k', a[3] = 'a';
  while (T--) {
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; ++i) std::cin >> s[i];
    int cnt = 0, okay = 0;
    for (int j = 0; j < m; ++j) {
      for (int i = 1; i <= n; ++i) {
        if (s[i][j] == a[cnt]) {
          ++cnt;
          break;
        }
      }
      if (cnt == 4) { okay = 1; break; }
    }
    puts(okay ? "YES" : "NO");
  }
  return 0;
}

B. Sequence Game

Problem

題目

Sol & Code

升序直接接到答案序列後,降序先加個一在答案序列後再加入答案序列。

#include <bits/stdc++.h>
#define N 200001

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n, ans[N << 1];

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    int last, cnt = 0;
    scanf("%d", &last);
    ans[++cnt] = last;
    for (int i = 2, x; i <= n; ++i) {
      scanf("%d", &x);
      if (x >= last) { ans[++cnt] = x; last = x; }
      else { ans[++cnt] = 1, ans[++cnt] = x; last = x; }
    }
    printf("%d\n", cnt);
    for (int i = 1; i <= cnt; ++i) {
      printf("%d ", ans[i]);
    }
    puts("");
  }
  return 0;
}

C. Flower City Fence

Problem

題目

Sol & Code

長度爲 \(n\) 的木板會對 \(1\sim n\)\(1\) 的貢獻,可以差分記錄貢獻最後看兩種擺放時候一致。

#include <bits/stdc++.h>
#define N 200518

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int T, n, a[N], ans[N];

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) ans[i] = 0, scanf("%d", &a[i]);
    std::sort(a + 1, a + n + 1);
    if (a[n] != n) { puts("NO"); continue; }
    for (int i = 1; i <= n; ++i) {
      ++ans[1], --ans[a[i] + 1];
    }
    bool okay = true;
    for (int i = 1; i <= n; ++i) {
      ans[i] += ans[i - 1];
      if (ans[i] != a[n - i + 1]) { okay = false; break; }
    }
    if (okay) puts("YES");
    else puts("NO");
  }
  return 0;
}

D. Ice Cream Balls

Problem

題目

Sol & Code

\(n\) 種不同的球有 \(\dfrac{n(n-1)}{2}\) 種不同的組合,相同種類的球有 \(1\) 種組合,計算出不超出題目要求的最大的 \(n\) 最後加上剩餘數量即可。

#include <bits/stdc++.h>

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

ll n;
int T;

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%lld", &n);
    ll k = sqrt(2ll * n);
    while (k * (k - 1) <= 2ll * n) ++k;
    while (k * (k - 1) > 2ll * n) --k;
    printf("%lld\n", k + (n - k * (k - 1) / 2));
  }
  return 0;
}

E. Kolya and Movie Theatre

Problem

題目

Sol & Code

假設我們在 \(a,b,c\) 三天去看電影,那麼 \(d\) 的貢獻爲 \(-(a-0)d-(b-a)d-(c-b)d = -cd\) 可見 \(d\) 的貢獻只與最後是在哪天看的電影有關。

枚舉這個最後一天 \(x\),想要知道最後一天爲 \(x\) 的答案還要統計前 \(x - 1\) 個數中最多選 \(m - 1\) 個數的和的最大值,優先隊列可做。

#include <bits/stdc++.h>

typedef long long ll;
ll max(ll a, ll b) { return a > b ? a : b; }

int T, n, m, d;
std::priority_queue<int> q;

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d %d %d", &n, &m, &d);
    ll ans = 0, res = 0;
    for (int i = 1, x; i <= n; ++i) {
      scanf("%d", &x);
      if (x > 0) {
        if (q.size() < m) {
          q.push(-x);
          res += x;
        } else {
          if (-q.top() < x) {
            res += q.top();
            q.pop();
            res += x;
            q.push(-x);
          }
        }
        ans = max(ans, res - 1ll * i * d);
      }
    }
    printf("%lld\n", ans);
    while (!q.empty()) q.pop();
  }
  return 0;
}

F. Magic Will Save the World

Problem

題目

Sol & Code

發現時間越久成功概率越大即有單調性,二分答案。

問題來到了如何判斷是否可行。

問題可以轉化爲有兩個揹包,容量分別爲 \(a,b\) 能否將物品全部裝下,因此每個揹包要儘量裝,計算一次 \(0-1\) 揹包看剩下的物品能否用另一個揹包裝下即可。

複雜度好像有點懸,加個小優化。

#include <bits/stdc++.h>
#define N 101

typedef long long ll;

int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }

int g[1000518];
int T, n, w, f, s[N], pre[N];

bool check(int k) {
  ll a = 1ll * k * w, b = 1ll * k * f;
  for (int i = 0; i <= n; ++i) {
    if (pre[i] <= a && pre[n] - pre[i] <= b) return true;
    if (pre[i] > a) break;
  }
  for (int i = a; i >= 0; --i) g[i] = 0;
  for (int i = 1; i <= n; ++i) {
    for (int j = a; j >= s[i]; --j) {
      g[j] = max(g[j], g[j - s[i]] + s[i]);
    }
  }
  return (pre[n] - g[a] <= b);
}

int main() {
  scanf("%d", &T);
  while (T--) {
    scanf("%d %d", &w, &f);
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
      scanf("%d", &s[i]);
      pre[i] = pre[i - 1] + s[i];
    }
    int l = 1, r = 1000000;
    while (l <= r) {
      int mid = (l + r) >> 1;
      if (check(mid)) r = mid - 1;
      else l = mid + 1;
    }
    printf("%d\n", r + 1);
  }
  return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章