ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Aising Programming Contest 2022(AtCoder Beginner Contest 255)

2022-06-12 01:02:35  阅读:250  来源: 互联网

标签:std AtCoder le Beginner Contest int i64 ++


ABC比较简单,DF过于经典。

E - Lucky Numbers

题意

给定一个长度为\(n - 1\)的数组\(s\),和长度为\(m\)的数组\(t\)。

要求构造出一个满足\(\forall i \in [1, n - 1], a_i + a_{i + 1} = s_i\)的数组\(a\),并且最大化满足\(a_i \in \{t_i | 1 \le i \le m\}\)的\(i\)的数量。

思路

观察可得:\(a_0\)确定了,则\(a\)就确定了。

观察可得:\(a_0\)加1,则后面奇数位都得减1,偶数位都得加1。所以其他位置的修改可以映射成\(a_0\)的修改。

考虑初始时令\(a_0 = 0\),然后计算其他\(a_i\)。

注意到目标集合的大小是很小的,所以可以对于每个\(a_i\),枚举目标集合中的数,看自身和目标的差距,然后将这个差距映射到\(a_0\)的增量,统计增量出现的次次数。

出现次数最多的增量,它的出现次数就是答案。

AC代码
// Problem: E - Lucky Numbers
// Contest: AtCoder - Aising Programming Contest 2022(AtCoder Beginner Contest 255)
// URL: https://atcoder.jp/contests/abc255/tasks/abc255_e
// Memory Limit: 1024 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  // std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

void solve_case(int Case) {
  int n, m;
  std::cin >> n >> m;

  std::vector<i64> s(n - 1), t(m);
  for (int i = 0; i < n - 1; ++i)
    std::cin >> s[i];
  for (int i = 0; i < m; ++i)
    std::cin >> t[i];

  std::vector<i64> a(n);
  a[0] = 0;
  for (int i = 0; i < n - 1; ++i) {
    a[i + 1] = s[i] - a[i];
  }

  std::map<i64, int> cnt;
  for (int i = 0; i < n; ++i) {
    if (i & 1) {
      for (int j = 0; j < m; ++j) {
        i64 d = t[j] - a[i];
        ++cnt[d];
      }
    } else {
      for (int j = 0; j < m; ++j) {
        i64 d = t[j] - a[i];
        ++cnt[-d];
      }
    }
  }

  int ans = 0;
  for (auto [k, v] : cnt) {
    ans = std::max(ans, v);
  }

  std::cout << ans << "\n";
}

G - Constrained Nim

TBA。

Ex - Range Harvest Query

题意

有\(n\)个资源点,第\(i\)个资源点每天刷新\(i\)个资源。

有\(q\)个操作\((d_i, l_i, r_i)\):在第\(d_i\)天收割\([l_i, r_i]\)的资源,输出收割到的资源数,答案对\(998244353\)取模。

其中\(1 \le n \le {10}^{18}, 1 \le q \le 2 \times {10}^5,1 \le d_1 < d_2 <> \dots <> d_q \le {10}^{18}, 1\le l_i \le r_i \le {10}^{18}\)。

思路

卡G了,没看这道题,感觉比G简单。

std::set维护每个位置上一次收割的时间,把相同时间收割的区间合并成1个元素,类似Chtholly Tree。

一次收割\((D, L, R)\)可以对应拆分,删除,插入三种操作:

  1. 左右边界所在区间可能没有被\([L, R]\)完全包含,所以可能需要将左右边界不完整的区间拆分出来
  2. 现在集合中\([L, R]\)内的区间都是完全属于\([L, R]\)的了,对于\([L, R]\)内的区间统计贡献,然后删除
  3. 最后再插入区间\([L, R]\),值全为\(D\)。

对于区间\([l, r]\),假设上一次收割的时间为\(last\),本次收割的时间为\(d\),则这段区间对于答案的贡献为

\[\sum_{i = l}^{r} i (d - last) = \frac{(d - last) * (l + r) * (r - l + 1)}{2} \]

初始时只有1个元素,每次收割插入一个元素,删除的元素最差不会超过插入元素的总数的3倍,由此插入和删除区间的总数为\(O(q)\),总的复杂度为\(O(n \log q)\)。

AC代码
// Problem: Ex - Range Harvest Query
// Contest: AtCoder - Aising Programming Contest 2022(AtCoder Beginner Contest 255)
// URL: https://atcoder.jp/contests/abc255/tasks/abc255_h
// Memory Limit: 1024 MB
// Time Limit: 8000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>

#define CPPIO std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
#define freep(p) p ? delete p, p = nullptr, void(1) : void(0)

#ifdef BACKLIGHT
#include "debug.h"
#else
#define logd(...) ;
#endif

using i64 = int64_t;
using u64 = uint64_t;

void solve_case(int Case);

int main(int argc, char* argv[]) {
  CPPIO;
  int T = 1;
  // std::cin >> T;
  for (int t = 1; t <= T; ++t) {
    solve_case(t);
  }
  return 0;
}

const int mod = 998244353;
int add(int x, int y) {
  return x + y >= mod ? x + y - mod : x + y;
}
int sub(int x, int y) {
  return x - y < 0 ? x - y + mod : x - y;
}
int mul(int x, int y) {
  return i64(1) * x * y % mod;
}
int qp(int x, int y) {
  int r = 1;
  while (y) {
    if (y & 1)
      r = mul(r, x);
    x = mul(x, x);
    y >>= 1;
  }
  return r;
}
int inv(int x) {
  return qp(x, mod - 2);
}
const int inv2 = inv(2);

void solve_case(int Case) {
  i64 n, q;
  std::cin >> n >> q;
  std::set<std::array<i64, 3>> s;
  s.insert({1, n, 0});

  auto split = [&](i64 x) {
    if (x > n)
      return;
    auto it = --s.lower_bound({x + 1, 0, 0});
    auto [l, r, d] = (*it);
    if (l == x)
      return;
    s.erase(it);
    s.insert({l, x - 1, d});
    s.insert({x, r, d});
  };

  auto query = [&](i64 l, i64 r, i64 d) {
    auto cost = [](int l, int r, int z) {
      return mul(mul(z, mul(add(l, r), add(sub(r, l), 1))), inv2);
    };
    logd(l, r, d);

    logd(s);
    split(r + 1);
    logd(s);
    split(l);
    logd(s);

    int ans = 0;
    i64 p = l;
    while (p <= r) {
      auto it = s.lower_bound({p, 0, 0});
      auto [L, R, D] = (*it);
      s.erase(it);
      logd(s);

      ans = (ans + cost(L % mod, R % mod, (d - D) % mod)) % mod;
      p = R + 1;
    }
    s.insert({l, r, d});
    logd(s);

    return ans;
  };

  for (int _ = 0; _ < q; ++_) {
    i64 d, l, r;
    std::cin >> d >> l >> r;
    std::cout << query(l, r, d) << "\n";
  }
}

标签:std,AtCoder,le,Beginner,Contest,int,i64,++
来源: https://www.cnblogs.com/zengzk/p/16367221.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有