ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #811 (Div. 3)

2022-08-02 02:00:39  阅读:165  来源: 互联网

标签:std 10 int Codeforces back ++ vector 811 Div


咕咕咕。

D. Color with Occurrences

题意

给定文本串\(t\),和\(n\)个模式串\(s_i\)。

初始时\(t\)的每个字符都是黑色的,如果\(t\)的某个子串和\(s_i\)相等,则可以通过一次染色将这个子串中的字符都染成红色。

一个模式串可以用多次,\(t\)中的一个字符可以被染色多次,红色的字符再次染色的结果还是红色。

问染色几次可以把\(t\)中所有字符染成红色,要求出输出次数以及方案。

其中\(1 \le |t| \le 100, 1 \le n, |s_i| \le 10\)。

思路

如果\(t_{l} t_{l+1} \dots t_{r}\)和某个\(s_i\)相等,则对于\(l \le i \le r\),向\(r + 1\)连边,表示从\(i\)可以转移到\(r + 1\)。这个由于参数比较小,直接暴力就可以了。

然后跑个最短路就可以得到最小染色次数,方案数就是再记录个路径。

AC代码
// Problem: D. Color with Occurrences
// Contest: Codeforces - Codeforces Round #811 (Div. 3)
// URL: https://codeforces.com/contest/1714/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

const int INF = 0x3f3f3f3f;

void solve_case(int Case) {
  std::string t;
  std::cin >> t;
  int m = static_cast<int>(t.size());

  std::vector<std::vector<int>> f(m + 1, std::vector<int>(m + 1, INF));
  std::vector<std::vector<int>> g(m + 1, std::vector<int>(m + 1, -1));
  std::vector<std::vector<int>> h(m + 1, std::vector<int>(m + 1, -1));
  std::vector<std::vector<int>> w(m + 1, std::vector<int>(m + 1, -1));

  int n;
  std::cin >> n;
  for (int k = 0; k < n; ++k) {
    std::string s;
    std::cin >> s;
    int l = static_cast<int>(s.size());

    if (l > m)
      continue;

    for (int i = 0; i + l - 1 < m; ++i) {
      bool flag = true;
      for (int j = 0; j < l; ++j) {
        if (t[i + j] != s[j]) {
          flag = false;
          break;
        }
      }
      if (flag) {
        for (int j = i; j < i + l; ++j) {
          f[j][i + l] = 1;
          g[j][i + l] = k;
          h[j][i + l] = i + l;
          w[j][i + l] = i;
        }
      }
    }
  }

  for (int k = 0; k <= m; ++k) {
    for (int i = 0; i <= m; ++i) {
      for (int j = 0; j <= m; ++j) {
        if (f[i][j] > f[i][k] + f[k][j]) {
          f[i][j] = f[i][k] + f[k][j];
          h[i][j] = h[i][k];
        }
      }
    }
  }

  if (f[0][m] == INF) {
    std::cout << "-1\n";
  } else {
    std::cout << f[0][m] << "\n";
    int p = 0;
    while (p != m) {
      logd(p);
      int q = h[p][m];
      std::cout << g[p][q] + 1 << " " << w[p][q] + 1 << "\n";
      p = q;
    }
  }
}

E. Add Modulo 10

题意

给定长度为\(n\)的数组\(a\)。支持下述这一操作:

  • 选择一个\(i\),令\(a_i = a_i + (a_i \mod 10)\)。

同一个\(i\)可以选择多次。问通过零或多次操作,是否能够使\(a\)中所有数相等。

其中\(1 \le n \le 2 \times {10}^5, 0 \le a_i \le {10}^9\)。

思路

根据\(a_i \mod 10\)分类讨论,假设数\(x\)个位数为\(y\),那么假设对\(x\)进行一次操作过后的得到\(z\),则有\(z\)的个位数为\(2y \mod 10\)。根据这个把转移图建出来。

然后就可以发现转移图可以分成两个部分\(\{0, 5\}\)和其他。

对于个位数为\(0\)的数\(x\),继续对\(x\)进行操作\(x\)也不会发生变化。

对于个位数为\(5\)的数\(x\),对\(x\)进行一次操作过后,再继续对\(x\)进行操作\(x\)也不会发生变化。

对于其余情况,可以无止境的对\(x\)进行操作,每次操作都会得到一个新的数,且其个位数的变化满足\(\dots \to 2 \to 4 \to 8 \to 6 \to 2 \to \dots\)。

观察1:假设对\(a_i\)操作\(t_i\)次得到的结果满足条件,那么对所有\(t_i\)同时加上某个自然数,结果依然满足条件。

由此,不妨对所有个位数为\(5\)的数先操作一次,转成个位数为\(0\)的数。

然后,如果存在个位数为\(0\)的数,那么有解当且仅当\(a\)中所有元素已经相等了。

现在,只需要考虑没有数个位数为\(0\)且没有数个位数为\(5\)的情况。

观察2:此时,通过有限次操作一定可以使\(x\)的个位数为\(6\)。

观察3:对于个位数为\(6\)的数\(x\),对\(x\)进行操作直到下一次\(x\)个位数为\(6\)时,\(\frac{x - 6}{10}\)的值增加了\(2\),即\(\frac{x - 6}{10}\)的奇偶性不会改变。

由此,不妨先将所有数个位数搞成\(6\),然后看\(\frac{x - 6}{10}\)的奇偶性,有解当且仅当对于所有\(x\),\(\frac{x - 6}{10}\)同奇偶。

AC代码
// Problem: E. Add Modulo 10
// Contest: Codeforces - Codeforces Round #811 (Div. 3)
// URL: https://codeforces.com/contest/1714/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n;
  std::cin >> n;

  std::vector<int> a(n);
  for (int i = 0; i < n; ++i) {
    int x;
    std::cin >> x;

    if (x % 10 == 0)
      ;
    else if (x % 10 == 5) {
      x = x + 5;
    } else {
      while (x % 10 != 6) {
        x = x + x % 10;
      }
    }

    a[i] = x;
  }

  std::vector<int> c(10);
  for (int x : a) {
    ++c[x % 10];
  }

  bool flag;
  if (c[0] > 0) {
    int ma = *std::max_element(a.begin(), a.end());
    int mi = *std::min_element(a.begin(), a.end());
    flag = ma == mi;
  } else {
    std::vector<int> d(2);
    for (int x : a) {
      ++d[(x - 6) / 10 % 2];
    }
    flag = !(d[0] > 0 && d[1] > 0);
  }

  std::cout << (flag ? "Yes" : "No") << "\n";
}

F. Build a Tree and That Is It

题意

给定4个数\(n, d_{12}, d_{23}, d_{31}\),要求构造出满足下述条件的一颗树:

  • 树有\(n\)个节点。
  • 节点1到节点2的距离为\(d_{12}\)。
  • 节点2到节点3的距离为\(d_{23}\)。
  • 节点3到节点1的距离为\(d_{31}\)。

其中\(3 \le n \le 2 \times {10}^5\)。

思路

假设构造下面这种形状的树, //表示零或多条边。

        1
       //
       x
     // \\
     2   3

令\(d(u, v)\)表示\(u\)到\(v\)的距离。记\(d(1, x) = a, d(x, 2) = b, d(x, 3) = c\),则有

\[\left\{ \begin{aligned} d_{12} = a + b\\ d_{23} = b + c\\ d_{31} = a + c\\ \end{aligned} \right. \]

然后就可以解出\(a, b, c\)。

\(a, b, c\)必须为整数且不能为负数,否则无解。

若\(b, c\)同时为零,2和3这两个点重合,无解。

构建这个树至少需要\(a + b + c + 1\)个点,当\(a + b + c + 1 > n\)时无解。

然后可以根据\(c\)是否等于零分类讨论,再模拟一下即可。

AC代码
// Problem: F. Build a Tree and That Is It
// Contest: Codeforces - Codeforces Round #811 (Div. 3)
// URL: https://codeforces.com/contest/1714/problem/F
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n, d12, d23, d31;
  std::cin >> n >> d12 >> d23 >> d31;

  if ((d12 + d23 - d31) % 2 != 0) {
    std::cout << "NO\n";
    return;
  }

  int b = (d12 + d23 - d31) / 2;
  int a = d12 - b;
  int c = d31 - a;
  logd(a, b, c);

  if (a < 0 || b < 0 || c < 0 || (b == 0 && c == 0) || a + b + c > n - 1) {
    std::cout << "NO\n";
    return;
  }

  std::vector<std::pair<int, int>> E;
  std::vector<int> p;

  if (c > 0) {
    int u = 1, x = 4;
    p.push_back(1);
    for (int i = 0; i < a + b - 1; ++i) {
      E.push_back(std::make_pair(p.back(), x));
      p.push_back(x);
      ++x;
    }
    E.push_back(std::make_pair(p.back(), 2));
    p.push_back(2);

    for (int i = 0; i < b; ++i) {
      p.pop_back();
    }

    for (int i = 0; i < c - 1; ++i) {
      E.push_back(std::make_pair(p.back(), x));
      p.push_back(x);
      ++x;
    }
    E.push_back(std::make_pair(p.back(), 3));
    p.push_back(3);

    while (x <= n) {
      E.push_back(std::make_pair(p.back(), x));
      p.push_back(x);
      ++x;
    }
  } else {
    int u = 1, x = 4;
    p.push_back(1);
    for (int i = 0; i < a - 1; ++i) {
      E.push_back(std::make_pair(p.back(), x));
      p.push_back(x);
      ++x;
    }
    E.push_back(std::make_pair(p.back(), 3));
    p.push_back(3);

    for (int i = 0; i < b - 1; ++i) {
      E.push_back(std::make_pair(p.back(), x));
      p.push_back(x);
      ++x;
    }
    E.push_back(std::make_pair(p.back(), 2));
    p.push_back(2);

    while (x <= n) {
      E.push_back(std::make_pair(p.back(), x));
      p.push_back(x);
      ++x;
    }
  }

  std::cout << "YES\n";
  for (auto [u, v] : E) {
    std::cout << u << " " << v << "\n";
  }
}

G. Path Prefixes

这题好水,不详细写了。

大概就是DFS记录到根的路径,然后二分。

AC代码
// Problem: G. Path Prefixes
// Contest: Codeforces - Codeforces Round #811 (Div. 3)
// URL: https://codeforces.com/contest/1714/problem/G
// Memory Limit: 256 MB
// Time Limit: 3000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n;
  std::cin >> n;

  std::vector<std::vector<int>> g(n);
  std::vector<int> a(n), b(n);
  for (int i = 1; i < n; ++i) {
    int p;
    std::cin >> p >> a[i] >> b[i];
    --p;
    g[p].push_back(i);
  }

  std::vector<int> r(n);
  i64 SA = 0, SB = 0;
  std::vector<i64> B;
  std::function<void(int)> dfs = [&](int u) {
    SA += a[u], SB += b[u];
    B.push_back(SB);

    if (u != 0) {
      r[u] = std::upper_bound(B.begin(), B.end(), SA) - B.begin() - 1;
      logd(u, SA, B, r[u]);
    }

    for (int v : g[u]) {
      dfs(v);
    }

    SA -= a[u], SB -= b[u];
    B.pop_back();
  };
  dfs(0);

  for (int i = 1; i < n; ++i)
    std::cout << r[i] << " \n"[i + 1 == n];
}

标签:std,10,int,Codeforces,back,++,vector,811,Div
来源: https://www.cnblogs.com/zengzk/p/16542400.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有