《如 何 速 通 一 套 題》3

hhc0001發表於2024-07-02

A election

定數:普及+,普及-,普及-,無,總計普及。

(思維,實現,演算法,資料結構,總計)

雙指標,每一次只會打死最左的和最右的,計算是死左邊還是死右邊即可。

\(O(N \log N) - O(1)\)

code
#include <bits/stdc++.h>
using namespace std;

struct node {
  int x, id;
}arr[1000010];

int n, xx[1000010];

int lrmid(int x, int y) {
  int l = arr[x].x, r = arr[y].x, ans = 0;
  for(; l <= r; ) {
    int mid = (l + r) >> 1;
    //cout << mid << ' ' << mid - arr[x].x << ' ' << arr[y].x - mid << '\n';
    if((mid - arr[x].x) > (arr[y].x - mid)) {
      ans = mid, r = mid - 1;
    }else {
      l = mid + 1;
    }
  }
  return ans;
}

int main() {
  freopen("election.in", "r", stdin);
  freopen("election.out", "w", stdout);
  cin >> n;
  for(int i = 1; i <= n; i++) {
    cin >> arr[i].x;
    arr[i].id = i;
  }
  sort(arr + 1, arr + n + 1, [](node a, node b) {return a.x < b.x;});
  for(int i = 1; i <= n; i++) {
    xx[i] = arr[i].x;
  }
  int i = 1, j = n;
  for(; i < j; ) {
    int a = lrmid(i, j);
    int tmp = lower_bound(xx + i, xx + j + 1, a) - xx;
    //cout << i << ' ' << j << ' ' << arr[i].id << ' ' << arr[j].id << ' ' << a << ' ' << tmp << '\n';
    if((tmp - i) >= j - tmp + 1) {
      j--;
    }else {
      i++;
    }
  }
  cout << arr[i].id << '\n';
  return 0;
}

B chaos

定數:提高,普及+,無,無,總計提高。

死因:現象看到了,本質沒看到

如下:

1 2 3 4 5 [k = n - 1]
1 5 4 3 2 [k += 3]
1 3 4 5 2 [k += 2]

如此以往......
有一些操作不會進行。一樣是正確的。

\(O(N) - O(N)\)

code
#include <bits/stdc++.h>
#define int long long
using namespace std;

int n, k, pos[100010], arr[100010];

signed main() {
  freopen("chaos.in", "r", stdin);
  freopen("chaos.out", "w", stdout);
  cin >> n >> k;
  k -= n - 1;
  pos[1] = 1;
  for(int i = 2, l = 2, r = n, rv = 0; i <= n; i++) {
    if(k >= n - i) {
      k -= n - i;
      rv ^= 1;
    }
    if(rv) {
      pos[i] = r;
      r--;
    }else {
      pos[i] = l;
      l++;
    }
  }
  for(int i = 1; i <= n; i++) {
    arr[pos[i]] = i;
  }
  for(int i = 1; i <= n; i++) {
    cout << arr[i] << ' ';
  }
  cout << '\n';
  return 0;
}

C defend

定數:提高,普及+,普及+,無,總計提高。

死因:沒有想到最佳化

定義 \(dp_{x, lst}\) 為最後一個為 \(x\),上一個為 \(lst\) 時至多能搞到幾個人。

發現很難轉移,於是引入一個輔助陣列 \(dash\)

\(dash_{x, k}\) 表示當前為 \(x\),當前與上一個的 \(\operatorname{and}\) 的第 \(k\) 為固定為 \(1\) 時至多能搞到幾個人。

然後就可以用 \(dash\) 最佳化 \(dp\) 了。

點選檢視程式碼
#include <bits/stdc++.h>
using namespace std;

int n, arr[2020], ans, dp[2020][2020], cnt[2020][110]; // dash is counted from the third number... or not?

int main() {
  freopen("defend.in", "r", stdin);
  freopen("defend.out", "w", stdout);
  cin >> n;
  for(int i = 1; i <= n; i++) {
    cin >> arr[i];
  }
  arr[0] = arr[n + 1] = INT_MAX;
  //cout << DFS(0, 0) - 2 << '\n';
  for(int i = 1; i <= n; i++) {
    dp[i][0] = 1;
    for(int j = 31; j >= 0; j--) {
      cnt[i][j] = 1;
    }
  }
  for(int i = 1; i <= n; i++) {
    for(int j = 0; j < i; j++) {
      if(!j) {
        ans = max(ans, dp[i][j]);
        for(int k = 31; k >= 0; k--) {
          if((arr[j] >> k) & 1) {
            cnt[i][k] = max(cnt[i][k], dp[i][j]); // Update dash
          }
        }
        continue;
      }
      int x = (arr[i] & arr[j]);
      if(x) {
        dp[i][j] = 1;
        for(int k = 31; k >= 0; k--) {
          if((x >> k) & 1) {
            dp[i][j] = max(dp[i][j], cnt[j][k] + 1); // If there can be a dash
          }
        }
        for(int k = 31; k >= 0; k--) {
          if((arr[j] >> k) & 1) {
            cnt[i][k] = max(cnt[i][k], dp[i][j]); // Update dash
          }
        }
        ans = max(ans, dp[i][j]);
      }
      //cout << dp[i][j] << ' ';
    }
    //cout << '\n';
  }
  cout << max(min(n, 2), ans) << '\n';
  return 0;
}

D standin

定數:提高-,普及+,提高,無,總計提高-。

死因:沒有輸出 -1

一開始我想列舉寬頻,後來發現不用,具體見下圖:

T4.bmp

可以看到,直接按照寬頻大小,從小到大轉移即可。

\(O(N2^M) - O(2^M)\)

點選檢視程式碼
#include <bits/stdc++.h>
#define int long long
using namespace std;

struct node {
  int x, k, mask;
}arr[110];

int dp[1 << 20], n, m, b, c, t, ans = LLONG_MAX;

signed main() {
  freopen("standin.in", "r", stdin);
  freopen("standin.out", "w", stdout);
  cin >> n >> m >> b;
  for(int i = 1; i <= n; i++) {
    for(cin >> arr[i].x >> arr[i].k >> c; c--; ) {
      cin >> t;
      arr[i].mask |= (1 << (t - 1));
    }
  }
  sort(arr + 1, arr + n + 1, [](node a, node b) {return a.k < b.k;});
  memset(dp, 0x3f, sizeof(dp));
  dp[0] = 0;
  for(int i = 1; i <= n; i++) {
    for(int j = (1 << m) - 1; j >= 0; j--) {
      dp[j | arr[i].mask] = min(dp[j | arr[i].mask], dp[j] + arr[i].x);
    }
    if(dp[(1 << m) - 1] != 0x3f3f3f3f3f3f3f3f) {
      ans = min(ans, dp[(1 << m) - 1] + arr[i].k * b);
    }
  }
  cout << (ans == LLONG_MAX? -1 : ans) << '\n';
  return 0;
}

相關文章