星环8.30笔试

ak了,代码做了点改动来更易读,有可能有地方有点小问题。

A

给你一个数组,每次操作你能选两个数,把较小的放到数组头部,较大的数放数组尾部,问最少多少次操作能将数组变为升序。

类似于贪心?或者说dp?感觉是乱搞搞。

#include <bits/stdc++.h>
using namespace std;
void solve() {
  int n;
  cin >> n;
  vector<int> dp(n + 1, 0);
  int nm = n;
  for (int i = 1; i <= n; i++) {
    int x;
    cin >> x;
    dp[x] = dp[x - 1] + 1;
    nm = min(nm, max(x - dp[x], n - x));
  }
  cout << nm << "\n";
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int t;
  cin >> t;
  while (t--) solve();
  return 0;
}

B

给你一棵树,n个操作,每个操作有两种:

+ 1 x 表示输出x节点所有子节点权值和

+ 2 x 表示将x的最重子节点与自己旋转,最重子节点指的是它的所有子节点里子树节点数量最多的节点

模拟一下就行了

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 5;
vector<int> g[MAXN];
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<long long> a(n);
  for (auto &x : a) cin >> x;
  for (int i = 1; i < n; i++) {
    int a, b;
    cin >> a >> b;
    a--, b--;
    g[a].push_back(b);
    g[b].push_back(a);
  }
  vector<long long> cnt(n), val(n), f(n);
  auto cmp = [&](int x, int y) {
    return cnt[x] != cnt[y] ? cnt[x] > cnt[y] : x < y;
  };
  vector<set<int, decltype(cmp)>> sons(n, set<int, decltype(cmp)>(cmp));
  auto dfs = [&](auto &dfs, int now, int fa) -> void {
    f[now] = fa;
    for (auto x : g[now]) {
      if (x != fa) {
        dfs(dfs, x, now);
        cnt[now] += cnt[x];
        val[now] += val[x];
        sons[now].insert(x);
      }
    }
    cnt[now]++;
    val[now] += a[now];
  };
  dfs(dfs, 0, -1);
  int root = 0;
  auto remove_from = [&](int x, int fa) {
    sons[fa].erase(x);
    val[fa] -= val[x];
    cnt[fa] -= cnt[x];
  };
  auto insert_into = [&](int x, int fa) {
    cnt[fa] += cnt[x];
    val[fa] += val[x];
    sons[fa].insert(x);
  };
  while (m--) {
    int t, x;
    cin >> t >> x;
    t--;
    x--;
    if (t == 0) {
      cout << val[x] << "\n";
    } else {
      if (sons[x].empty()) continue;
      if (x == root) {
        int t = *sons[x].begin();
        remove_from(t, x);
        insert_into(x, t);
        root = t;
        f[t] = -1;
        f[x] = t;
        continue;
      }
      int ff = f[x];
      int s = *sons[x].begin();
      remove_from(x, ff);
      remove_from(s, x);
      insert_into(x, s);
      insert_into(s, ff);
      f[x] = s;
      f[s] = ff;
    }
  }
  return 0;
}

C

给n个点,两个点距离表示为他们横纵坐标差的绝对值的最小值。求任意两点最大距离。

二分答案

#include <bits/stdc++.h>
using namespace std;
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  vector<array<long long, 2>> v(n);
  for (auto &x : v) cin >> x[0] >> x[1];
  sort(v.begin(), v.end());
  vector<int> ymina(n), ymaxa(n);
  vector<int> yminb(n), ymaxb(n);
  long long ymin = v[0][1];
  long long ymax = v[0][1];
  for (int i = 0; i < n; i++) ymina[i] = ymin = min(ymin, v[i][1]);
  for (int i = 0; i < n; i++) ymaxa[i] = ymax = max(ymax, v[i][1]);
  ymin = v.back()[1];
  ymax = v.back()[1];
  for (int i = n - 1; i >= 0; i--) yminb[i] = ymin = min(ymin, v[i][1]);
  for (int i = n - 1; i >= 0; i--) ymaxb[i] = ymax = max(ymax, v[i][1]);
  long long l = 0, r = 2e9 + 1;
  auto check = [&](long long t) {
    int r = 0;
    for (int i = 0; i < n; i++) {
      while (r < n && v[r][0] - v[i][0] < t) r++;
      if (r == n) return false;
      long long a[] = {ymina[i], ymaxa[i]};
      long long b[] = {yminb[r], ymaxb[r]};
      for (auto x : a)
        for (auto y : b)
          if (abs(x - y) >= t) return true;
    }
    return false;
  };
  while (l < r) {
    long long mid = (l + r) / 2;
    if (l + 1 == r) {
      if (check(r))
        l++;
      else
        r--;
    }
    if (check(mid))
      l = mid;
    else
      r = mid;
  }
  cout << l;
  return 0;
}

全部评论
🐮佬
点赞
送花
回复
分享
发布于 2023-08-30 22:05 湖北
大佬 可以说一下第一题的思路吗?没看懂
点赞
送花
回复
分享
发布于 2023-08-30 22:06 上海
秋招专场
校招火热招聘中
官网直投
请教一下第三题的思路
点赞
送花
回复
分享
发布于 2023-08-30 22:20 湖北

相关推荐

4 14 评论
分享
牛客网
牛客企业服务