2026/1/17-Atcoder Beginner Contest 441 T1~5

前言

比赛的时候只写了A~E后面结束后补,比赛链接:Atcoder 441
致力于把题目用通俗的语言翻译出来,让新人也能看懂


A

只要X Y范围在 (P,Q) 和 (P+99,Q+99)范围之间就成立

B

只要分成两个集合A,B
字符串中每一个字符都去匹配一下集合A,B就行了

C

题目人话:

有 N 个杯子,每个杯子里装了 Ai 毫升液体(比如杯子 1 装 10 毫升,杯子 2 装 8 毫升);
这 N 个杯子里,恰好有 K 个装的是清酒(剩下的都是水);
你不知道哪 K 个是清酒,只能盲选一些杯子(至少选 1 个);
要求:不管清酒藏在哪些杯子里,你选的这些杯子里的清酒总量,都至少有 X 毫升;
你的目标:找到满足要求的最少杯子数量;如果怎么选都做不到,就输出 - 1。

写题分析:

一,最坏情况

我们拿取杯子一定要按最坏情况来算,即清酒尽可能多的藏在没选的杯子里,且选中的杯子里的清酒都是容量小的那些,这样喝到的清酒才最少。

二,贪心策略

对于上面发生最坏情况,接下来是我们来选杯子,所以我们选杯子一定要从大往小选,即把杯子按照容量从大到小排序,接下来分三个大白话公式,假设选择m个杯子:

1,没选的杯子=总杯子N-选的数量m;
2,没选的杯子里的清酒=最多藏 min(K, 没选的杯子数) 杯
3,所以 选的杯子里的清酒 = K - 没选的杯子藏的清酒数

选的杯子中最小的那些杯数就是清酒的,累加这个容量和为sum;清酒杯数小于0则sum=0

三,枚举选择的杯数,前缀和优化

我们从小到大枚举杯子数量 m ,通过前缀和快速计算出喝到的清酒容量 sum ,再与 X 毫升判断;因为m从小到大,一找到就break。

代码:

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
#define eb emplace_back
#define all(x) (x).begin(), (x).end()
void solve()
{
  int n, k, x;
  cin >> n >> k >> x;
  vector<int> cup(n);

  for (int i = 0; i < n; i++)
  {
    cin >> cup[i];
  }
  sort(all(cup), greater<int>());
  vector<int> pre(n + 1, 0);
  for (int i = 0; i < n; i++)
  {
    pre[i + 1] = pre[i] + cup[i];
  }
  int ans = -1;
  for (int m = 1; m <= n; m++)
  {
    int s = min(k, n - m);
    int t = k - s;
    int wor = 0;
    if (t > 0)//杯子小于0的一律达斯
    {
      wor = pre[m] - pre[m - t];
    }
    if (wor >= x)//小于x毫升的也达斯
    {
      ans = m;
      break;
    }
  }
  cout << ans << "\n";
}

signed main()
{
  IOS;
  solve();
  return 0;
}

D

题目人话

地图上有 N 个地点(顶点),编号 1、2、…、N;
地点之间有 M 条 “单向路”(边),比如从地点 1 到地点 2 的路,走一次要花 20 “路费”(代价 C);
每个地点最多只有 4 条往外走的路(出度≤4);

从地点 1 出发,走恰好 L 步(每走一条路算 1 步,重复走同一条路也算步数);
要求走这 L 步的总路费,必须在 S 到 T 之间(比如 80≤总路费≤100);
找出所有满足条件的 “终点”(走到 L 步时停在哪个地点);
最后把这些终点按从小到大的顺序输出,没有就输出空行。

解题分析

1,观察题目

注意数据范围:1≤L≤10,走10步每一步最多4种选择,一共有410=1048576 ,所以可以用暴力枚举的方法来写。

2,实现分析

1,我们可以用dfs来完成这个题目,遇到满足直接加入dfs写法
2,我们还可以用动态规划的递推思想来完成这个题,设dp[k][u]=从点1出发,恰好走k步,到达地点u的所有路费方案的集合。递推方程为 dp[k-1][u]中沿着u的出边走一步的所有路费方案所构成集合 = dp[k]

代码

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(), (x).end()

using ll = long long;
using pii = pair<int, int>;
using pil = pair<int, long long>;
const int INF = 0x3f3f3f3f;
const int MAXN = 2e5 + 10;

vector<vector<pii>> g(MAXN);

vector<unordered_map<int, unordered_set<ll>>> dp;

void solve()
{
  int n, m, L, S, T;
  cin >> n >> m >> L >> S >> T;

  for (int i = 0; i < m; i++)
  {
    int u, v, c;
    cin >> u >> v >> c;
    g[u].eb(v, c);
  }

  dp.resize(L + 1);
  dp[0][1].insert(0);

  for (int k = 0; k < L; k++)
  {

    for (auto &[u, sum_set] : dp[k])
    {

      for (auto &[v, c] : g[u])
      {

        for (ll s : sum_set)
        {
          ll new_sum = s + c;

          if (new_sum > T)
            continue;
          dp[k + 1][v].insert(new_sum);
        }
      }
    }
  }

  vector<int> ans;
  for (auto &[v, sum_set] : dp[L])
  {

    for (ll s : sum_set)
    {
      if (s >= S && s <= T)
      {
        ans.pb(v);
        break;
      }
    }
  }

  sort(all(ans));
  for (int i = 0; i < ans.size(); i++)
  {
    if (i > 0)
      cout << " ";
    cout << ans[i];
  }
  cout << "\n";
}

signed main()
{
  IOS;
  int T;
  T = 1;
  while (T--)
  {
    solve();
  }

  return 0;
}

E

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define int long long 
#define pb push_back
#define eb emplace_back
#define all(x) (x).begin(), (x).end()

using ll = long long;
using pii = pair<int, int>;
using pil = pair<int, long long>;
const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 10;  
const int OFFSET = 5e5 + 5; 

struct BIT
{
  vector<int> tree;
  int size;

  BIT(int n) : size(n), tree(n + 1, 0) {}

  void update(int pos, int val = 1)
  {
    for (; pos <= size; pos += pos & -pos)
    {
      tree[pos] += val;
    }
  }

  int query(int pos)
  {
    int res = 0;
    for (; pos > 0; pos -= pos & -pos)
    {
      res += tree[pos];
    }
    return res;
  }
};

void solve()
{
  int n;
  string s;
  cin >> n >> s;

  vector<int> pre(n + 1, 0);
  for (int i = 1; i <= n; i++)
  {
    if (s[i - 1] == 'A')
      pre[i] = pre[i - 1] + 1;
    else if (s[i - 1] == 'B')
      pre[i] = pre[i - 1] - 1;
    else
      pre[i] = pre[i - 1];
  }
  vector<int> tmp = pre;
  sort(all(tmp));
  tmp.erase(unique(all(tmp)), tmp.end());
  int fen_size = tmp.size();
  BIT ft(fen_size);
  int idx0 = lower_bound(all(tmp), pre[0]) - tmp.begin() + 1;
  ft.update(idx0);
  int ans = 0;
  for (int r = 1; r <= n; r++)
  {
    int pos = lower_bound(all(tmp), pre[r]) - tmp.begin();
    ans += ft.query(pos);
    int idx = lower_bound(all(tmp), pre[r]) - tmp.begin() + 1;
    ft.update(idx);
  }
  cout << ans << "\n";
}

signed main()
{
  IOS;
  int T = 1;
  // cin >> T;
  while (T--)
  {
    solve();
  }
  return 0;
}
posted @ 2026-01-19 22:06  不太会a  阅读(5)  评论(0)    收藏  举报