首页 > 其他分享 >CF #575 Div3(A_F)

CF #575 Div3(A_F)

时间:2022-10-10 01:33:36浏览次数:82  
标签:std 奇数 int res CF 575 cin ++ Div3

A. Three Piles of Candies

题意:

给三个堆蛋糕,\(Alice\) 和 \(Bob\) 两个人分,要使得两人最后拿到手上的蛋糕数一样多,求两人最多可以获得多少蛋糕。

    void solve() {
        i64 a, b, c;
        std::cin >> a >> b >> c;
        std::cout << (a + b + c) / 2 << "\n";
    }

B. Odd Sum Segments

题意:

将一个数组分成连续的 \(k\) 段,使得每一段内各个数字之和是一个奇数。如果存在这种分法,输出 \(k\) 个区间的右端点,否则输出 \(No\)

思路:

根据奇数 + 奇数 = 偶数, 偶数 + 偶数 = 偶数奇数 + 偶数 = 奇数可知,要尽可能的让分出的区间数量多,就将每一个奇数分布在不同的区间内,这样奇数和奇数所产生的贡献就不会互相抵消掉。那么判断能不能分出 \(k\) 段区间,就是看这个区间内有多少个奇数。现在考虑分法,如果奇数的个数刚好等于 \(k\) 那么直接输出就好了;如果奇数个数大于 \(k\) ,就要考虑区间合并的问题了,因为 奇数+奇数 = 奇数,所以每一次如果只是两两合并的话,会将两个奇数变成偶数,导致现在这一段不满足条件,所以每一次合并的时候就是三个区间合并成为一个区间,也就相当于是每一次从最后面减掉两个区间,很明显任何一个数减去一个偶数不会改变它本身的奇偶性,所以在判断是否能够分出的时候,还要去考虑奇数的个数的奇偶性是不是和 \(k\) 的奇偶性是相同的。

    void solve() {
        int n, m;
        std::cin >> n >> m;
        std::vector<int> a(n + 1);
        i64 ans = 0;
        std::vector<int> res;
        for (int i = 1; i <= n; i++) {
            std::cin >> a[i];
            ans += a[i];
            if (ans & 1) {
                res.push_back(i);
                ans = 0;
            }
        }

        if (int(res.size()) % 2 == m % 2 && res.size() >= m) {
            std::cout << "Yes\n";
            while(res.size() > m) res.pop_back();
            res.back() = n;
            for (int i = 0; i < m; i++) std::cout << res[i] << " \n"[i == m - 1];
        } else {
            std::cout << "No\n";
        }
    }

C.Robot Breakout

题意:

有 \(n\) 个机器人在一个平面上,第 \(i\) 个机器人的位置是 \((X_i,Y_i)\)。在设计的时候,第 \(i\) 个机器人可以执行的操作:

  1. 位置从 \((X_i,Y_i)\) 变为 \((X_i-1,Y_i)\)。
  2. 位置从 \((X_i,Y_i)\) 变为 \((X_i,Y_i+1)\)。
  3. 位置从 \((X_i,Y_i)\) 变为 \((X_i+1,Y_i)\)。
  4. 位置从 \((X_i,Y_i)\) 变为 \((X_i,Y_i-1)\)。

但设计出现了缺陷,某些机器人可能不能执行上述的某些操作。你需要找一个点 \((A,H)\),使得 \(n\) 个机器人都可以到达 \((A,H)\) 。注意,一开始的位置在 \((A,H)\) 也算到达,且对于 \(A,H\) 的范围有限制 —— \(-10^5\leq A,H \leq 10^5\)。

思路:

对每一个功能进行分析,功能一缺失意味着这个机器人不能向左走,功能二缺失意味着机器人不能向上走,功能三缺失意味着这个机器人不能向右走,功能四缺失意味着这个机器人不能向下走。那么我们就可以根据机器人现在的位置来确定所能够移动的左右边界和上下边界。功能一来确定左边界,功能二来确定上边界,功能三来确定右边界,功能四来确定下边界。

   void solve() {
       int n; std::cin >> n;

       int x = -1E5, y = -1E5, xx = 1E5, yy = 1E5;
       for (int i = 0; i < n; i++) {
           int sx, sy, a, b, c, d;
           std::cin >> sx >> sy >> a >> b >> c >> d;
           if (!a) x = std::max(x, sx);
           if (!b) yy = std::min(yy, sy);
           if (!c) xx = std::min(xx, sx);
           if (!d) y = std::max(y, sy);
       }

       if (xx < x || yy < y) std::cout << 0 << "\n";
       else {
           std::cout << "1 " << x << " " << y << "\n";
       }

   }

D2.RGB Substring (hard version)

题意:

求修改字符串 \(s\) 多少次能够让其中的某一个子串(长度为 \(k\) )成为 \(RGBRGB\dots RGB\) 的子串。

思路:

\(D1\) 的话可以考虑爆力枚举出所有的子串来分别计算修改得次数。 \(D2\) 的话就需要去考虑优化的方案了。因为要求一个区间内修改次数的多少,而对于快速求区间和,不难想到用前缀和来优化这个过程。可以考虑用一个目标串 \(RGB\) 来计算当前位置需不需要修改,如果需要修改就在上一个位置的基础上加一。

    std::string aim = "RGB";
    std::vector<std::vector<int>> dp(3, std::vector<int> (n + 1));
 
    for (int i = 0; i < n; i++) 
        for (int j = 0; j < 3; j++) 
            dp[j][i + 1] = dp[j][i] + (s[i] == aim[(i + j) % 3] ? 0 : 1); 
            // 如果匹配上了,就不需要修改,否则修改次数 + 1

最后就是尺取出所有长度为 \(k\) 的子串然后计算修改次数

   void solve() {
       int n, k;
       std::cin >> n >> k;
       std::string s; std::cin >> s;
       std::string aim = "RGB";
       std::vector<std::vector<int>> dp(3, std::vector<int> (n + 1));

       for (int i = 0; i < n; i++) 
           for (int j = 0; j < 3; j++) 
               dp[j][i + 1] = dp[j][i] + (s[i] == aim[(i + j) % 3] ? 0 : 1);

       int ans = k;
       for (int i = 0; i <= n - k; i++) 
           for (int j = 0; j <= 2; j++) 
               ans = std::min(ans, dp[j][i + k] - dp[j][i]);
       std::cout << ans << "\n";
   }

E.Connected Component on a Chessboard

题意:

给出一个 \(10^9 × 10 ^ 9\) 的黑白棋盘( \(i + j\) 为奇数的时候是白色,否则为黑色),让我们构造出一个连通块使得黑色的点有 \(b\) 个,白色的点有 \(w\) 个,并输出构造方案。

思路:

画图可以发现,要想构成一个联通块的话,就必须要让所有的黑白点相邻,而且最优的情况就是尽量使得黑色/白色点的上下左右都选上。那么就考虑将最少的颜色 \(a\) 的点放在一条直线上,另一个颜色 \(b\) 插空,这样把 \(a\) 放置好了,就只需要去考虑将剩下的 \(b\) 都放置在 \(a\) 的上下方。

   void solve() {
       int b, w;
       std::cin >> b >> w;
       bool f = w > b;
       if (f) std::swap(w, b);

       std::vector<std::array<int, 2>> res;
       int x = 2, y = 2;
       while(w) {
           res.push_back({x, y});
           b -= (y & 1);
           w -= !(y & 1);
           y++;
       }

       int xx = 1, yy = 2;
       while(b && yy <= y) {
           res.push_back({xx, yy});
           b--, yy += 2;
       }
       int px = 3, py = 2;
       while(b && py <= y) {
           res.push_back({px, py});
           b--, py += 2;
       }

       if (b) res.push_back({2, 1}), b--;
       if (b) res.push_back({2, y}), b--;
       if (b) std::cout << "NO\n";
       else {
           std::cout << "YES\n";
           for (auto& now : res) 
            std::cout << now[0] << " " << now[1] + f << "\n";
       }
   }

F.K-th Path

题意:

给定一个无向带权连通图,求子节点两两之间路径从小到大排序之后第 \(k\) 长的路径长度。

思路:

首先,注意到 \(k\) 非常的小,如果只考虑边,那么最多有 \(k\) 条边会对答案产生影响,也就是说答案一定小于等于第 \(k\) 小的那条边。既然如此,对答案有影响的路径肯定也是由 \(k\) 条路径相互组合产生的,那么我们就知道了对答案有影响的点最多只有 \(k\) 级别的。那我们就只加前 \(k\) 小的边,然后对所有的被加过边的点跑最短路,然后用这个点到其他点的最短路去更新答案

      constexpr int N = 200010, M = N * 2;
          
      struct node {
          int v, w, nxt;
      }e[M];

      int idx, n, m, k, cnt;
      int h[N], a[N];
      i64 dist[N];
      bool vis[N], st[N];

      void add(int a, int b, int c) {
          e[++idx] = {b, c, h[a]}, h[a] = idx;
      }

      struct line {
          int u, v, w;
          bool operator< (const line& l) const {
              return w < l.w;
          }
      }edge[N];

      void dijkstra(int s) {
          for (int i = 1; i <= cnt; i++) {
              dist[a[i]] = 1E18;
              vis[a[i]] = false;
          }

          dist[s] = 0;
          std::priority_queue<pii, std::vector<pii>, std::greater<pii>> q;
          q.push({0, s});
          while(q.size()) {
              auto p = q.top(); q.pop();
              int u = p.second;

              if (vis[u]) continue;
              vis[u] = true;

              for (int i = h[u]; i; i = e[i].nxt) {
                  int v = e[i].v, w = e[i].w;
                  if (dist[v] > dist[u] + w) {
                      dist[v] = dist[u] + w;
                      if (!vis[v]) q.push({dist[v], v});
                  }
              }
          }
      }

      signed main() {
          std::cin.tie(nullptr)->sync_with_stdio(false);

          std::cin >> n >> m >> k;
          for (int i = 1; i <= m; i++) {
              int u, v, w;
              std::cin >> u >> v >> w;
              edge[i] = {u, v, w};
          }
          std::sort(edge + 1, edge + 1 + m);

          for (int i = 1; i <= std::min(m, k); i++) {
              add(edge[i].u, edge[i].v, edge[i].w);
              add(edge[i].v, edge[i].u, edge[i].w);

              if (!st[edge[i].u]) a[++cnt] = edge[i].u, st[edge[i].u] = true;
              if (!st[edge[i].v]) a[++cnt] = edge[i].v, st[edge[i].v] = true;
          }

          std::priority_queue<i64> q;

          for (int i = 1; i <= cnt; i++) {
              dijkstra(a[i]);
              for (int j = i + 1; j <= cnt; j++) {
                  q.push(-dist[a[j]]);
              }
          }

          for (int i = 1; i < k; i++) q.pop();
          std::cout << -q.top() << "\n";

          return 0 ^ 0;
      }

标签:std,奇数,int,res,CF,575,cin,++,Div3
From: https://www.cnblogs.com/Haven-/p/16774267.html

相关文章

  • CF896D Nephren Runs a Cinema 题解
    顺手搬一下吧···inluogu和其他题解不太一样的柿子。把0元,50元,100元分别看成\(-1\),\(0\),\(1\),则问题转化成有多少种由\(-1\),\(0\),\(1\),构成的长为\(n\)的序......
  • proxy_cfw全局代理_浏览器代理配置(chromium based(edge)/firefox/IDM)
    文章目录​​无须sstap等软件实现虚拟网卡代理​​​​reference​​​​配置步骤​​​​serviceMode​​​​tunMode​​​​检查启用情况​​​​edge浏览器内部代理......
  • CF1385E Directing Edges
    举例以这个图(\(1\)到\(5\)的边为无向边)为例。设每个点都有一个优先顺序,则有\(1\)的优先级大于\(2\),\(2\)的优先级大于\(3\),\(3\)的优先级大于\(4\),\(......
  • https://github.com/succlz123/AcFun-Client-Multiplatform
    GitHub-succlz123/AcFun-Client-Multiplatform:Athirdpartmultipaltformclientofhttps://www.acfun.cn/.Thegoalofthisrepositoryistobuildaonlinemed......
  • CCF推荐的A类、B类、C类中文科技期刊2022
    ​中国计算机学会(CCF)日前完成了《计算领域高质量科技期刊分级目录》审定工作,现予发布。2021年5月,CCF入选中国科协分领域发布高质量科技期刊分级目录项目,随后启动《计算领......
  • CF915E Physical Education Lessons
    题意Alex高中毕业了,他现在是大学新生。虽然他学习编程,但他还是要上体育课,这对他来说完全是一个意外。快要期末了,但是不幸的Alex的体育学分还是零蛋!Alex可不希望被开除,他......
  • CF962F Simple Cycles Edges
    CF962FSimpleCyclesEdges-洛谷|计算机科学教育新生态(luogu.com.cn)在一个无向图中,某个简单环等价于这个图中某个点数等于边数的点双连通分量。为什么不是边双......
  • CF1081E Missing Numbers
    大致是官方题解,因为题解里没有\(\mathcal{O(x\logx)}\)的做法。设\(x\)偶数项值域为\(V\)。设\(s_i=t_i^2=\sum\limits_{j=1}^{i}x_i\),随后\(V\gex_{2i......
  • CF1508C题解
    设题目给定的边为实边,未给出的为虚边容易发现2个性质:1.设所有实边的权值异或和为\(s\),则令一条未给出的边的权值为s,其他为0最优考虑求出虚边构成的连通块,这是个经典问题......
  • CF1256E. Yet Another Division Into Teams 题解 单调队列优化dp
    题目链接:https://codeforces.com/contest/1256/problem/E将\(n\)个数分成若干队,每一队至少包含\(3\)个整数,每一队的代价是最大值与最小值只差,求所有队伍代价之和的最......