Codeforces Round 954 (Div. 3)题解

  A

  直接暴力

int a, b, c;
void solve()
{
  cin >> a >> b >> c;
  int ans = 0, mi = inf;
  for (int i = -50; i <= 50;i++)
  {
    int num = abs(i - a) + abs(i - b) + abs(i - c);
    if (num < mi)
      mi = num;
  }
  cout << mi << "\n";
}
​

B

 直接暴力

int n, m, A[110][110];
int E[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
void solve()
{
  cin >> n >> m;
  for (int i = 1; i <= n;i++)
  {
    for (int j = 1; j <= m;j++)
    {
      cin >> A[i][j];
    }
  }
  for (int i = 1; i <= n;i++)
  {
    for (int j = 1; j <= m;j++)
    {
      vector<int> D;
      for (int k = 0; k < 4;k++)
      {
        int tx = i + E[k][0];
        int ty = j + E[k][1];
        if (tx <= 0||tx > n||ty <= 0||ty > m)
          continue;
        D.push_back(A[tx][ty]);
      }
      if ((int)D.size() == 0)
        continue;
      sort(D.begin(), D.end());
      int num = D[(int)D.size() - 1];
      if (num < A[i][j])
      {
        A[i][j] = num;
      }
    }
  }
  for (int i = 1; i <= n;i++)
  {
    for (int j = 1; j <= m;j++)
    {
      cout << A[i][j] << " ";
    }
    cout << "\n";
  }
}

C

直接暴力

int n, m;
string s, c;
int A[N];
void solve()
{
  cin >> n >> m;
  cin >> s;
  map<int, int> D;
  vector<char> B;
  for (int i = 1; i <= m; i++)
  {
    cin >> A[i];
    D[A[i]]++;
  }
  for (int i = 0; i < m; i++)
  {
    char x;
    cin >> x;
    B.push_back(x);
  }
  sort(A + 1, A + 1 + m);
  sort(B.begin(), B.end());
  int i = 0, j = m - 1;
  for (auto y : D)
  {
    int num = y.second;
    s[y.first - 1] = B[i++];
    j--;
  }
  cout << s << endl;
}

D

 就是肯定能加就加注意零特判

int n;
string s;
void solve()
{
  cin >> n;
  cin >> s;
  if (n <= 2)
  {
    int op = 0;
    for (int i = 0; i < n;i++)
    {
      if (s[i] != '0')
        op++;
      if (op)
        cout << s[i];
    }
    if (op == 0)
      cout << "0";
    cout << endl;
  }
  else if (n == 3)
  {
    LL ans = inf;
    for (int i = 0; i < n-1;i++)
    {
      LL num = (s[i] - '0') * 10 + s[i + 1] - '0';
      vector<int> Q;
      for (int j = 0; j < i;j++)
      {
        Q.push_back(s[j] - '0');
      }
      Q.push_back(num);
      for (int j = i + 2; j < n;j++)
      {
        Q.push_back(s[j] - '0');
      }
      LL num_ = 0, ww = 0;
      for (int j = 0; j < n - 1;j++)
      {
        if (ww == 0) 
        {
          ww++;
          num_ = Q[j];
        }
        else 
        {
          num_ = min(num_ + Q[j], num_ * Q[j]);
        }
      }
      ans = min(ans, num_);
    }
    cout << ans << endl;
  }
  else 
  {
    for (int i = 0; i < n;i++)
    { 
      if (s[i] == '0') 
      {
        cout << "0" << endl;
        return;
      }
    }
    LL ans = inf;
    for (int i = 0; i < n-1;i++)
    {
      LL num = (s[i] - '0') * 10 + s[i + 1] - '0';
      vector<int> Q;
      for (int j = 0; j < i;j++)
      {
        Q.push_back(s[j] - '0');
      }
      Q.push_back(num);
      for (int j = i + 2; j < n;j++)
      {
        Q.push_back(s[j] - '0');
      }
      LL num_ = 0, ww = 0;
      for (int j = 0; j < n - 1;j++)
      {
        if (ww == 0) 
        {
          ww++;
          num_ = Q[j];
        }
        else 
        {
          num_ = min(num_ + Q[j], num_ * Q[j]);
        }
      }
      ans = min(ans, num_);
    }
    cout << ans << endl;
  }
}

E

 按照因为加k,所以膜k不相等时肯定无法得到相同的数字, 按照奇数偶数分类奇数可以有一个放中间,每个类型的必须为偶数个数,n为奇数是可以允许一个为奇数,然后对称放,对于奇数个数的就暴力枚举一下选哪一个得到的最小操作数

int n, A[N], k;
bool cmp(int a, int b)
{
  if ((a % k) != (b % k))
    return (a % k) < (b % k);
  return a < b;
}
LL B[N], C[N];
void solve()
{
  cin >> n >> k;
  map<int, int> D;
  for (int i = 1; i <= n; i++)
  {
    cin >> A[i];
    D[(A[i] % k)]++;
  }
  sort(A + 1, A + 1 + n, cmp);
  int op = 0;
  for (auto y : D)
  {
    if (y.second & 1)
      op++;
  }
  if (op >= 2)
    cout << "-1" << endl;
  else
  {
    LL ans = 0;
    for (int i = 1; i <= n;)
    {
      if (D[(A[i] % k)] % 2 == 0)
      {
        for (int j = i + 1; j <= i + D[(A[i] % k)] - 1; j += 2)
          ans += (A[j] - A[j - 1]) / k;
        i += D[(A[i] % k)];
      }
      else
      {
        for (int j = i; j <= i + D[(A[i] % k)]; j += 2)
          B[j] = (A[j + 1] - A[j]) / k;
        for (int j = i + D[(A[i] % k)] - 1; j >= i; j -= 2)
          C[j] = (A[j] - A[j - 1]) / k;
        for (int j = i; j <= i + D[(A[i] % k)]; j++)
          B[j] += B[j - 1];
        for (int j = i + D[(A[i] % k)] - 1; j >= i; j--)
          C[j] += C[j + 1];
        LL num_ = C[i + 2];
        for (int j = i + 2; j <= i + D[(A[i] % k)]; j += 2)
          num_ = min(B[j - 1] + C[j + 1], num_);
        for (int j = i + 1; j <= i + D[(A[i] % k)] - 1; j += 2)
          num_ = min(B[j - 2] + C[j + 2] + (A[j + 1] - A[j - 1]) / k, num_);
        ans += num_;
        i += D[(A[i] % k)];
        memset(B, 0, sizeof(B));
        memset(C, 0, sizeof(C));
      }
    }
    cout << ans << endl;
  }
}

F

 板子题,现场找板子,没改过来,难绷了,找图的桥分开,两边节点个数分别为n,m,为n*(n-1)/2+m*(m-1)/2,取最小值

#define int long long
void solve()
{
  int n, m, tot = 0, cnt = 0, now = 0;
  LL ans = 1e18;
  cin >> n >> m;
  vector<pair<int, int>> A[n + 1];
  vector<int> dfn(n + 1), low(n + 1), siz(n + 1), vis(n + 1);
  stack<int> stk;
  for (int i = 1; i <= m; i++)
  {
    int u, v;
    cin >> u >> v;
    A[u].push_back({v, i});
    A[v].push_back({u, i});
  }
  function<void(int, int)> tarjan = [&](int x, int id) -> void
  {
    dfn[x] = low[x] = ++tot;
    stk.push(x);
    for (auto [y, id2] : A[x])
    {
      if (!dfn[y])
      {
        tarjan(y, id2);
        low[x] = min(low[x], low[y]);
      }
      else if (id != id2)
        low[x] = min(low[x], dfn[y]);
    }
    if (dfn[x] == low[x])
    {
      ++cnt;
      while (1)
      {
        int y = stk.top();
        stk.pop();
        if (y == x)
          break;
      }
      ans = min(ans, siz[x] * (siz[x] - 1) / 2 + (n - siz[x]) * (n - siz[x] - 1) / 2);
    }
  };
  function<void(int, int)> dfs = [&](int x, int fa) -> void
  {
    siz[x] = 1;
    vis[x] = 1;
    for (auto [y, id] : A[x])
    {
      if (y == x || vis[y])
        continue;
      dfs(y, x);
      siz[x] += siz[y];
    }
  };
  dfs(1, -1);
  for (int i = 1; i <= n; i++)
  {
    if (!dfn[i])
      tarjan(i, -1);
  }
  cout << ans << endl;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值