Loading

AtCoder Beginner Contest 352 考试总结

前言

正常发挥。属于是 \(4\) 个月没搞 OI,复健成功了!

image

得分明细:

A B C D E F G Total
× × 1475

改题明细:

A B C D E F G
× ×

第一次正式 rated 打 AT,行吧!

A. AtCoder Line

Problem

AtCoder 铁路线有 \(N\) 个车站,编号为 \(1, 2, \ldots, N\)

在这条线路上,有趟进站列车\(1\) 站出发,依次停靠 \(2, 3, \ldots, N\) 站,有趟出站列车\(N\) 站出发,依次停靠 \(N - 1, N - 2, \ldots, 1\) 站。

高桥站即将从 \(X\) 站前往 \(Y\) 站,只需使用进站和出站列车中的一列。

求列车在 \(Z\) 站停留的时间。

Solve

\(\{z\in [x,y]|x\le y\}\) 即为 "Yes",否则即为 "No"。

Code

#include <bits/stdc++.h>
#define ll long long
#define H 19260817
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
#define MOD 1000003
#define mod 1000000007

using namespace std;

inline int read() {
  rint x=0,f=1;char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  return x*f;
}

void print(int x){
  if(x<0){putchar('-');x=-x;}
  if(x>9){print(x/10);putchar(x%10+'0');}
  else putchar(x+'0');
  return;
}

int n, x, y, z;

signed main() {
  n = read(), x = read(), y = read(), z = read();
  if(x > y) swap(x, y);
  if(x <= z && z <= y) puts("Yes");
  else puts("No");
  return 0;
}

B. Typing

Problem

高桥尝试使用键盘输入由小写英文字母组成的字符串 \(S\)

他打字时只看键盘,不看屏幕,实际键入的字符串是 \(T\)

\(T\) 中没有被误输入的字符称为正确输入字符

确定正确键入的字符在 \(T\) 中的位置。

Solve

指针 \(i\) 指着 \(S\) 一边判一边扫即可。

Code

#include <bits/stdc++.h>
#define ll long long
#define H 19260817
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
#define MOD 1000003
#define mod 1000000007

using namespace std;

inline int read() {
  rint x=0,f=1;char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  return x*f;
}

void print(int x){
  if(x<0){putchar('-');x=-x;}
  if(x>9){print(x/10);putchar(x%10+'0');}
  else putchar(x+'0');
  return;
}

const int N = 2e5 + 10;

int n, m;

char s[N], t[N];

signed main() {
  cin >> (s + 1) >> (t + 1);
  n = strlen(s + 1), m = strlen(t + 1);
  int i = 1;
  For(j,1,m) {
    if(s[i] == t[j]) cout << j << ' ', i++;
  }
  return 0;
}

C. Standing On The Shoulders

Problem

\(N\) 个巨人,他们的名字分别是 \(1\)\(N\)。当巨人 \(i\) 站在地上时,他们的肩高是 \(A_i\),头高是 \(B_i\)

你可以选择 \((1, 2, \ldots, N)\)\((P_1, P_2, \ldots, P_N)\) 排列组合,并根据以下规则堆叠 \(N\) 个巨人:

  • 首先,将巨人 \(P_1\) 放在地上。巨人 \(P_1\) 的肩膀距离地面的高度为 \(A_{P_1}\),头部距离地面的高度为 \(B_{P_1}\)
  • 为了 \(i = 1, 2, \ldots, N - 1\) 的顺序,要把巨人 \(P_{i + 1}\) 放在巨人 \(P_i\) 的肩膀上。如果巨人 \(P_i\) 的肩膀距离地面的高度是 \(t\),那么巨人 \(P_{i + 1}\) 的肩膀距离地面的高度就是 \(t + A_{P_{i + 1}}\),他们的头距离地面的高度就是 \(t + B_{P_{i + 1}}\)

求最上面的巨人 \(P_N\) 的头部距离地面的最大可能高度。

Solve

考虑到每种排列的叠加总高度为某 \(n-1\) 个巨人的肩高加上剩下 \(1\) 个巨人的头高。

则答案为:\(\max\limits_{1\le i \le n}\sum\limits_{j=1,i\not=j}^{n}A_j+B_i\)

Code

#include <bits/stdc++.h>
#define int long long
#define H 19260817
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
#define MOD 1000003
#define mod 1000000007

using namespace std;

inline int read() {
  rint x=0,f=1;char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  return x*f;
}

void print(int x){
  if(x<0){putchar('-');x=-x;}
  if(x>9){print(x/10);putchar(x%10+'0');}
  else putchar(x+'0');
  return;
}

const int N = 2e5 + 10;

struct Node {
  int a, b;
} a[N];

int n, res = 0, ans;

signed main() {
  n = read();
  For(i,1,n) a[i].a = read(), a[i].b = read(), res += a[i].a;
  For(i,1,n) {
    ans = max(ans, res - a[i].a + a[i].b);
  }
  cout << ans << '\n';
  return 0;
}

D. Permutation Subsequence

Problem

给你一个 \((1, 2, \dots, N)\) 的排列组合 \(P = (P_1, P_2, \dots, P_N)\)

如果一个索引序列 \((i_1, i_2, \dots, i_K)\) 同时满足以下两个条件,那么这个索引序列被称为好索引序列

  • \(1 \leq i_1<i_2<\dots<i_K \leq N\)
  • 子序列 \((P_{i_1}, P_{i_2}, \dots, P_{i_K})\) 可以通过重新排列一些连续的 \(K\) 整数而得到。
    形式上,存在一个整数 \(a\) ,使得 \(\lbrace P_{i_1},P_{i_2},\dots,P_{i_K} \rbrace = \lbrace a,a+1,\dots,a+K-1 \rbrace\)

求所有好的索引序列中 \(i_K - i_1\) 的最小值。可以证明,在此问题的约束条件下,至少存在一个好的索引序列。

Solve

\(a_{p_i} = i\),发现答案贡献区间为一个宽度为 \(k\) 的窗口。

滑动窗口求 max/min 即可。

Code

#include <bits/stdc++.h>
#define int long long
#define H 19260817
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
#define MOD 1000003
#define mod 1000000007

using namespace std;

inline int read() {
  rint x=0,f=1;char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  return x*f;
}

void print(int x){
  if(x<0){putchar('-');x=-x;}
  if(x>9){print(x/10);putchar(x%10+'0');}
  else putchar(x+'0');
  return;
}

const int N = 2e5 + 10;

int n, k, p[N], a[N], q[N], Max[N], Min[N], ans = INT_MAX;

signed main() {
  n = read(), k = read();
  For(i,1,n) p[i] = read(), a[p[i]] = i;
  int h = 1, t = 0;
  For(i,1,n) {
    while(h <= t && i - q[h] + 1 > k) h++;
    while(h <= t && a[i] < a[q[t]]) t--;
    q[++t] = i;
    if(i >= k) {
      Min[i] = a[q[h]];
    }
  }
  h = 1, t = 0;
  For(i,1,n) {
    while(h <= t && i - q[h] + 1 > k) h++;
    while(h <= t && a[i] > a[q[t]]) t--;
    q[++t] = i;
    if(i >= k) {
      Max[i] = a[q[h]];
    }
  }
  For(i,k,n) {
    ans = min(ans, Max[i] - Min[i]);
  }
  cout << ans << '\n';
  return 0;
}

E. Clique Connect

Problem

给你一个加权无向图 \(G\),其中有 \(N\) 个顶点,编号为 \(1\)\(N\) 。最初,\(G\) 没有边。

您将执行 \(M\) 次操作为 \(G\) 添加边。\(i\)-th 操作 \((1 \leq i \leq M)\) 如下:

  • 给你一个由 \(K_i\) 个顶点组成的顶点子集 \(S_i=\lbrace A_{i,1},A_{i,2},\dots,A_{i,K_i}\rbrace\)。对于每一对 \(u, v\) 这样的顶点 \(u, v \in S_i\)\(u < v\),在顶点 \(u\)\(v\) 之间添加一条边,边的权重为 \(C_i\)

完成所有 \(M\) 操作后,确定 \(G\) 是否相连。如果是,求 \(G\) 最小生成树中各条边的总重。

Solve

一个组内的点与其连边组成的图必为一个,团内两两联通,且边权相等。

考虑 kruskal,先决策边权最小的团。然后暴力团内 kruskal。

加两个限制:

  1. 如果当前点已经在团内联通,就不需要加边了,跳过此回合;
  2. 如果此时生成树的边数已经为 \(n-1\),结束决策;

记得先判连通,再进行决策,不然最后一点会 T 掉。(赛时没注意罚时 \(4\) 次)

然后就 A 了。

Code

#include <bits/stdc++.h>
#define int long long
#define H 19260817
#define rint register int
#define For(i,l,r) for(rint i=l;i<=r;++i)
#define FOR(i,r,l) for(rint i=r;i>=l;--i)
#define MOD 1000003
#define mod 1000000007

using namespace std;

inline int read() {
  rint x=0,f=1;char ch=getchar();
  while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  return x*f;
}

void print(int x){
  if(x<0){putchar('-');x=-x;}
  if(x>9){print(x/10);putchar(x%10+'0');}
  else putchar(x+'0');
  return;
}

const int N = 4e5 + 10;

struct Eg {
  int k, c;
} b[N];

int n, m, f[N], p[N], ans, net;

vector<int> a[N];

bool vis[N];

bool cmp(int x, int y) {
  return b[x].c < b[y].c;
}

int find(int x) {
  return (x == f[x] ? x : f[x] = find(f[x]));
}

signed main() {
  n = read(), m = read();
  For(i,1,n) f[i] = i;
  For(i,1,m) {
    p[i] = i;
    b[i] = (Eg){read(), read()};
    For(j,1,b[i].k) {
      int x = read();
      a[i].push_back(x);
      f[find(a[i][0])] = find(a[i][a[i].size()-1]);
    }
  }
  int res = 0;
  For(i,1,n) {
    if(find(i) != find(1)) res++; 
  }
  if(res) return puts("-1"), 0;
  For(i,1,n) f[i] = i;
  sort(p + 1, p + m + 1, cmp);
  For(i,1,m) {
    int tg = i; i = p[i];
    For(j,0,b[i].k-1) {
      if(vis[find(a[i][j])]) continue;
      For(k,j+1,b[i].k-1) {
        int u = a[i][j], v = a[i][k];
        int fu = find(u), fv = find(v);
        if(fu == fv) continue;
        f[fu] = fv; vis[fu] = 1;
        ans += b[i].c; net++;
        if(net == n-1) goto yzsy;
      }
    }
    i = tg;
  }
  yzsy: ;
  cout << ans << '\n';
  return 0;
}

F. Clique Connect

Problem

\(N\) 人,编号为 \(1\)\(N\)

在这些 \(N\) 人中举行了一次竞赛,并对他们进行了相应的排名。有关他们的排名信息如下:

  • 每个人都有一个唯一的排名。
  • 对于每个 \(1 \leq i \leq M\),如果 \(A_i\) 的排名是 \(x\) -th,而 \(B_i\) 的排名是 \(y\)-th,那么就是 \(x - y = C_i\)

给定的输入保证了至少有一种可能的排名与给定的信息不矛盾。

回答 \(N\) 个查询。 \(i\)-th查询的答案是一个整数,确定方法如下:

  • 如果可以唯一确定人 \(i\) 的排名,则返回该排名。否则,返回 \(-1\)

Solve

Code

G. Socks 3

Problem

高桥的抽屉里有各种颜色的袜子。袜子的颜色用从 \(1\)\(N\) 的整数表示,其中有 \(A_i\geq 2\) 只袜子的颜色是 \(i\)

他准备通过执行以下操作来选择今天要穿的袜子:

  • 继续以相等的概率从箱子中每次随机抽取一只袜子,直到他能从已抽取的袜子中做出一双相同颜色的袜子为止。一旦抽到袜子,就不能再放回箱子里。

求他从箱子中抽取袜子的次数的期望值(模为 \(998244353\))。

Solve

Code

posted @ 2024-05-04 22:58  Daniel_yzy  阅读(213)  评论(1编辑  收藏  举报