首页 > 其他分享 >20241002

20241002

时间:2024-10-02 19:44:15浏览次数:1  
标签:return 20241002 int tr mid dfs dp

bwtree

我们可以设 \(dp_{i, 0/1}\) 表示当前考虑至哪个点,这个节点的子树内选了几个叶子节点

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5 + 5, INF = 1e9;

int n, a[N], dp[N][2];

vector<int> g[N];

void dfs(int u, int f) {
  dp[u][0] = (a[u] == 1);
  dp[u][1] = (a[u] == 0);
  if ((g[u].size() == 1 && g[u][0] == f) || g[u].size() == 0) {
    return ;
  }
  for (auto v : g[u]) {
    if (v == f) {
      continue;
    }
    dfs(v, u);
  }
  int ans = 0, tot = 0, mini = INF;
  for (auto v : g[u]) {
    if (v == f) {
      continue;
    }
    if (dp[v][0] > dp[v][1]) {
      ans += dp[v][0];
    }
    else {
      ans += dp[v][1];
      tot += 1;
    }
    mini = min(mini, max(dp[v][0], dp[v][1]) - min(dp[v][0], dp[v][1]));
  }
  dp[u][tot % 2] += ans;
  dp[u][(tot + 1) % 2] += ans - mini;
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  freopen("bwtree.in", "r", stdin);
  freopen("bwtree.out", "w", stdout);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
  }
  for (int i = 1, u, v; i < n; i++) {
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  dfs(1, 0);
  cout << max(dp[1][0], dp[1][1]);
  return 0;
}

prison

一眼题,但是忘了 \(tarjan\) 如何写,答案就是强连通分块数量,连接不同强连通分量之间的边数

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N = 1e5 + 5;

int n, m, dfn[N], cnt, ans, res[N], a[N], tot;

bool vis[N];

vector<int> g[N];

stack<int> stk;

void dfs(int u) {
  dfn[u] = ++cnt;
  res[u] = dfn[u];
  vis[u] = true;
  stk.push(u);
  for (auto v : g[u]) {
    if (!dfn[v]) {
      dfs(v);
      res[u] = min(res[u], res[v]);
    }
    else if (vis[v]) {
      res[u] = min(res[u], dfn[v]);
    }
  }
  if (res[u] == dfn[u]) {
    tot++;
    while (stk.top() != u) {
      a[stk.top()] = tot;
      vis[stk.top()] = false;
      stk.pop();
    }
    a[u] = tot;
    vis[u] = false;
    stk.pop();
  }
}

signed main() {
  freopen("prison.in", "r", stdin);
  freopen("prison.out", "w", stdout);
  cin >> n >> m;
  for (int i = 1, opt, u, v; i <= m; i++) {
    cin >> opt >> u >> v;
    if (opt == 0) {
      g[u].push_back(v);
      g[v].push_back(u);
    }
    else {
      g[u].push_back(v);
    }
  }
  for (int i = 1; i <= n; i++) {
    if (!dfn[i]) {
      dfs(i);
    }
  }
  for (int i = 1; i <= n; i++) {
    for (auto v : g[i]) {
      ans += (a[v] != a[i]);
    }
  }
  cout << tot << " " << ans;
  return 0;
}

placement

我们来拆式子

\[a[i] \times i - b[i] \times (n - i + 1) \\ a[i] \times i - b[i] \times n + b[i] \times i - b[i]\\ (a[i] + b[i]) \times i - (n + 1) \times b[i] \]

那么式子中的 \(b[i] \times (n + 1)\) 就是确定的了,所以我们只需要关心 \(a[i] + b[i]\),更具式子,显然我们要让 \(a[i] + b[i]\) 大的靠后放,那么我们想让答案最大的形式就已经确定了,我们只能交换 \(a[i] + b[i]\) 相等的数,此题完结

#include <bits/stdc++.h>

using namespace std;

#define int long long

const int N = 1e5 + 5, mod = 1e9 + 7;

struct node {
  int a, b;
}x[N];

int n, inv[N], ans = 1;

bool cmp(node _x, node _y) {
  return _x.a + _x.b < _y.a + _y.b;
}

signed main() {
  freopen("placement.in", "r", stdin);
  freopen("placement.out", "w", stdout);
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> x[i].a;
  }
  for (int i = 1; i <= n; i++) {
    cin >> x[i].b;
  }
  inv[1] = 1;
  for (int i = 2; i <= 100000; i++) {
    inv[i] = inv[i - 1] * i % mod;
  }
  sort(x + 1, x + n + 1, cmp);
  for (int i = 1; i <= n; i++) {
    if (x[i].a + x[i].b != x[i - 1].a + x[i - 1].b) {
      int p = i;
      while (p <= n && x[p].a + x[p].b == x[i].a + x[i].b) {
        p++;
      }
      ans = ans * inv[p - i] % mod;
    }
  }
  cout << ans;
  return 0;
}

hierarchy

我们可以维护一堆\(set\),表示职级为 \(a\) 的工资有哪些,\(set\) 为大根堆,我们还可以开一个线段树维护职级为 \([l, r]\) 的最大工资,然后我们在每次往下递归时每次从 \(set\)里删除掉,然后再在回溯时加上即可,然后我们在每次删掉是更新一下线段树

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;

int t, n, a[N], b[N], maxia[N], maxib[N], c[N], p[N], cnt, tr[N * 4];

vector<int> g[N];

multiset<int, greater<int>> s[N];

bool flag;

void build(int i, int l, int r) {
  if (l == r) {
    if (!s[l].empty()) {
      tr[i] = *s[l].begin();
    }
    else tr[i] = 0;
    return ;
  }
  int mid = (l + r) >> 1;
  build(i * 2, l, mid);
  build(i * 2 + 1, mid + 1, r);
  tr[i] = max(tr[i * 2], tr[i * 2 + 1]);
}

void modify(int i, int l, int r, int p) {
  if (l == r) {
    if (!s[l].empty()) {
      tr[i] = *s[l].begin();
    }
    else tr[i] = 0;
    return ;
  }
  int mid = (l + r) >> 1;
  if (mid >= p) {
    modify(i * 2, l, mid, p);
  }
  else modify(i * 2 + 1, mid + 1, r, p);
  tr[i] = max(tr[i * 2], tr[i * 2 + 1]);
}

int query(int i, int l, int r, int x, int y) {
  if (x > y) {
    return 0;
  }
  if (l > y || r < x) {
    return 0;
  }
  if (l >= x && r <= y) {
    return tr[i];
  }
  int mid = (l + r) >> 1;
  return max(query(i * 2, l, mid, x, y), query(i * 2 + 1, mid + 1, r, x, y));
}

void dfs(int u, int f) {
  for (auto v : g[u]) {
    if (v == f) {
      continue;
    }
    dfs(v, u);
    maxia[u] = max(maxia[v], maxia[u]);
    maxib[u] = max(maxib[v], maxib[u]);
  }
  if (maxia[u] > a[u] || maxib[u] > b[u]) {
    flag = false;
  }
  maxia[u] = a[u], maxib[u] = b[u];
}

void dfs1(int u, int f) {
  s[a[u]].erase(s[a[u]].find(b[u]));
  modify(1, 1, cnt, a[u]);
  for (auto v : g[u]) {
    if (v == f) {
      continue;
    }
    dfs1(v, u);
  }
  int tmp = query(1, 1, cnt, a[u], cnt);
  if (tmp >= b[u]) {
    flag = false;
  }
  s[a[u]].insert(b[u]);
  modify(1, 1, cnt, a[u]);
}

void Solve() {
  cin >> n;
  for (int i = 1; i <= n; i++) {
    cin >> a[i] >> b[i];
    c[i] = a[i];
    g[i].clear();
    maxia[i] = 0, maxib[i] = 0;
    s[i].clear();
  }
  cnt = 0;
  sort(c + 1, c + n + 1);
  for (int i = 1; i <= n; i++) {
    if (c[i - 1] != c[i]) p[++cnt] = c[i];
  }
  for (int i = 1; i <= n; i++) {
    a[i] = lower_bound(p + 1, p + cnt + 1, a[i]) - p;
    s[a[i]].insert(b[i]);
  }
  build(1, 1, cnt);
  for (int i = 1, u, v; i < n; i++) {
    cin >> u >> v;
    g[u].push_back(v);
    g[v].push_back(u);
  }
  flag = true;
  dfs(1, 0);
  dfs1(1, 0);
  if (!flag) {
    cout << "NO\n";
  }
  else cout << "YES\n";
}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> t;
  while (t--) {
    Solve();
  }
  return 0;
}

标签:return,20241002,int,tr,mid,dfs,dp
From: https://www.cnblogs.com/libohan/p/18445024

相关文章