【CodeForces】Educational Codeforces Round 47 题解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/82219813

【比赛链接】

【题解链接】

**【A】**Game Shopping

【思路要点】

  • 按照题意模拟。
  • 时间复杂度 O ( N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
int a[MAXN], b[MAXN];
int main() {
  int n, m; read(n), read(m);
  for (int i = 1; i <= n; i++)
      read(a[i]);
  for (int i = 1; i <= m; i++)
      read(b[i]);
  int ans = 0, pos = 1;
  for (int i = 1; i <= n && pos <= m; i++)
      if (b[pos] >= a[i]) {
          pos++;
          ans++;
      }
  writeln(ans);
  return 0;
}

**【B】**Minimum Ternary String

【思路要点】

  • 题目中 0 2 的相对位置始终不会发生改变,可以看做 1 可以自由移动, 0 2 留在原地。
  • 将所有 1 插入到第一个 2 之前即可,若没有出现 2 ,则插到字符串末尾。
  • 时间复杂度 O ( N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
char s[MAXN];
int main() {
  scanf("%s", s + 1);
  int n = strlen(s + 1), cnt = 0;
  for (int i = 1; i <= n; i++)
      if (s[i] == '1') cnt++;
  for (int i = 1; i <= n; i++)
      if (s[i] != '1') {
          if (s[i] == '0') putchar(s[i]);
          else {
              if (cnt > 0) while (cnt--) putchar('1');
              putchar(s[i]);
          }
      }
  if (cnt > 0) while (cnt--) putchar('1');
  return 0;
}

**【C】**Annoying Present

【思路要点】

  • 使平均数最大即为使总和最大,若 d i 0 ,则选择在 1 号位置操作,否则在中间位置操作即可。
  • 中间量可能很大,需要 l o n g   d o u b l e
  • 时间复杂度 O ( M )

【代码】

扫描二维码关注公众号,回复: 3029252 查看本文章

#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
int n, m; long double ans;
long long calc(int x, int y) {
  int len = y - x + 1;
  return 1ll * (x + y) * len / 2;
}
int main() {
  read(n), read(m);
  for (int i = 1; i <= m; i++) {
      int x, d; read(x), read(d);
      ans += x * n;
      if (d >= 0) ans += d * calc(0, n - 1);
      else {
          if (n & 1) ans += 2 * d * calc(0, n / 2);
          else ans += d * (calc(0, n / 2) + calc(0, n / 2 - 1));
      }
  }
  printf("%.10Lf\n", ans / n);
  return 0;
}

**【D】**Relatively Prime Graph

【思路要点】

  • 特判图不可能联通的情况,剩余部分暴力即可。
  • 由于 i = 1 600 ϕ ( i ) 10 5 M ,我们至多搜索 600 N 个点对就可以找到答案。
  • 时间复杂度 O ( 600 N L o g N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
int gcd(int x, int y) {
  if (y == 0) return x;
  else return gcd(y, x % y);
}
int tot, x[MAXN], y[MAXN];
int main() {
  int n, m; read(n), read(m);
  if (m < n - 1) {
      printf("Impossible\n");
      return 0;
  }
  for (int i = 1; i <= n; i++)
  for (int j = i + 1; j <= n; j++)
      if (gcd(i, j) == 1) {
          tot++; x[tot] = i, y[tot] = j;
          if (tot == m) {
              printf("Possible\n");
              for (int k = 1; k <= m; k++)
                  printf("%d %d\n", x[k], y[k]);
              return 0;
          }
      }
  printf("Impossible\n");
  return 0;
}

**【E】**Intercity Travelling

【思路要点】

  • 分开考虑每一个 a i 的贡献, a i 在第 i 段路程被计算了 2 n i 次,在第 i + 1 N 段每一段被计算了 2 n i 1 次。
  • 因此
    A n s = i = 1 N a i ( 2 n i + ( n i ) 2 n i 1 )
  • 时间复杂度 O ( N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 1e6 + 5;
const int P = 998244353;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
int power(int x, int y) {
  if (y == 0) return 1;
  int tmp = power(x, y / 2);
  if (y % 2 == 0) return 1ll * tmp * tmp % P;
  else return 1ll * tmp * tmp % P * x % P;
}
int bit[MAXN];
int main() {
  int n; read(n);
  bit[0] = 1;
  for (int i = 1; i <= n; i++)
      bit[i] = bit[i - 1] * 2 % P;
  int ans = 0;
  for (int i = 1; i <= n; i++) {
      int x; read(x);
      ans = (ans + 1ll * x * bit[n - i]) % P;
      if (i != n) ans = (ans + 1ll * x * bit[n - i - 1] % P * (n - i)) % P;
  }
  writeln(ans);
  return 0;
}

**【F】**Dominant Indices

【思路要点】

  • 用线段树合并算出每一个节点 i d i , ,并维护区间最大值以便查询即可。
  • 时间复杂度 O ( N L o g N )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 1e6 + 5;
const int MAXP = 2.5e7 + 5;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
struct SegmentTree {
  struct Node {
      int lc, rc;
      int Max;
  } a[MAXP];
  int size, n;
  void init(int x) {
      n = x;
      size = 0;
  }
  void update(int root) {
      a[root].Max = max(a[a[root].lc].Max, a[a[root].rc].Max);
  }
  int modify(int root, int l, int r, int val) {
      int ans = ++size;
      a[ans] = a[root];
      if (l == r) {
          a[ans].Max++;
          return ans;
      }
      int mid = (l + r) / 2;
      if (mid >= val) a[ans].lc = modify(a[root].lc, l, mid, val);
      else a[ans].rc = modify(a[root].rc, mid + 1, r, val);
      update(ans);
      return ans;
  }
  int modify(int root, int val) {
      return modify(root, 1, n, val);
  }
  int merge(int ra, int rb, int l, int r) {
      if (ra == 0 || rb == 0) return ra + rb;
      if (l == r) {
          a[ra].Max += a[rb].Max;
          return ra;
      }
      int mid = (l + r) / 2;
      a[ra].lc = merge(a[ra].lc, a[rb].lc, l, mid);
      a[ra].rc = merge(a[ra].rc, a[rb].rc, mid + 1, r);
      update(ra);
      return ra;
  }
  int merge(int ra, int rb) {
      return merge(ra, rb, 1, n);
  }
  int query(int root, int l, int r) {
      if (l == r) return l;
      int mid = (l + r) / 2;
      if (a[root].Max == a[a[root].lc].Max) return query(a[root].lc, l, mid);
      else return query(a[root].rc, mid + 1, r);
  }
  int query(int root) {
      return query(root, 1, n);
  }
} ST;
int n, ans[MAXN], root[MAXN];
vector <int> a[MAXN];
void dfs(int pos, int fa, int depth) {
  root[pos] = ST.modify(root[pos], depth);
  for (unsigned i = 0; i < a[pos].size(); i++)
      if (a[pos][i] != fa) {
          dfs(a[pos][i], pos, depth + 1);
          root[pos] = ST.merge(root[pos], root[a[pos][i]]);
      }
  ans[pos] = ST.query(root[pos]) - depth;
}
int main() {
  read(n);
  ST.init(n);
  for (int i = 1; i <= n - 1; i++) {
      int x, y; read(x), read(y);
      a[x].push_back(y);
      a[y].push_back(x);
  }
  dfs(1, 0, 1);
  for (int i = 1; i <= n; i++)
      writeln(ans[i]);
  return 0;
}

**【G】**Allowed Letters

【思路要点】

  • 检查是否存在合法解实际上就是检查二分图是否存在完美匹配。
  • 考虑 H a l l 定理,由于二分图一侧的点数很小 ( 6 ) ,我们可以直接暴力套用 H a l l 定理来检验是否存在合法解。
  • 强制匹配一条边后检验是否存在完美匹配是 O ( 2 6 ) 的。
  • 时间复杂度 O ( 6 2 6 | S | )

【代码】


#include<bits/stdc++.h>

using namespace std;
const int MAXN = 100005;
const int MAXS = 1 << 6;
const int MAXC = 7;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); } 
template <typename T> void read(T &x) {
  x = 0; int f = 1;
  char c = getchar();
  for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
  x *= f;
}
template <typename T> void write(T x) {
  if (x < 0) x = -x, putchar('-');
  if (x > 9) write(x / 10);
  putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {
  write(x);
  puts("");
}
char s[MAXN];
int n, m, goal, bit[MAXC], a[MAXN], cnt[MAXS], sum[MAXS];
bool tryans(int bit, int pos) {
  for (int i = 0; i <= goal; i++) {
      if (i & bit) cnt[i]--;
      if (i & a[pos]) sum[i]--;
  }
  for (int j = 0; j <= goal; j++) {
      if (cnt[j] > sum[j]) {
          for (int i = 0; i <= goal; i++) {
              if (i & bit) cnt[i]++;
              if (i & a[pos]) sum[i]++;
          }
          return false;
      }
  }
  return true;
}
int main() {
  scanf("%s", s + 1);
  n = strlen(s + 1), read(m);
  for (int i = 1; i <= 6; i++)
      bit[i] = 1 << (i - 1);
  goal = (1 << 6) - 1;
  for (int i = 1; i <= n; i++)
      a[i] = goal;
  for (int i = 1; i <= m; i++) {
      int pos; char tmp[15];
      scanf("%d %s", &pos, tmp + 1);
      int len = strlen(tmp + 1), tans = 0;
      for (int j = 1; j <= len; j++)
          tans += bit[tmp[j] - 'a' + 1];
      a[pos] = tans;
  }
  for (int i = 1; i <= n; i++) {
      int tmp = bit[s[i] - 'a' + 1];
      for (int j = 0; j <= goal; j++) {
          if (j & tmp) cnt[j]++;
          if (j & a[i]) sum[j]++;
      }
  }
  for (int i = 0; i <= goal; i++)
      if (cnt[i] > sum[i]) {
          printf("Impossible\n");
          return 0;
      }
  for (int i = 1; i <= n; i++) {
      for (int j = 1; j <= 6; j++)
          if ((a[i] & bit[j]) != 0 && tryans(bit[j], i)) {
              putchar('a' + j - 1);
              break;
          }
  }
  printf("\n");
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39972971/article/details/82219813
今日推荐