《如 何 速 通 一 套 题》3

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;
}
posted @ 2024-07-02 14:09  hhc0001  阅读(9)  评论(0编辑  收藏  举报