CSP-S 2023 代码

T1 密码锁

// CSP-S 2023 密码锁
#include <bits/stdc++.h>
using namespace std;
using VI = vector<int>;
int main() {
#ifdef ONLINE_JUDGE
  freopen("lock.in", "r", stdin);
  freopen("lock.out", "w", stdout);
#endif
  int n;
  cin >> n;
  set<VI> AS;      // 输入的n种状态
  map<VI, int> M;  // 可能的一些来源状态
  VI A(5), B;
  for (int i = 0; i < n; i++) {
    for (int& a : A) cin >> a;
    AS.insert(A);
    for (int i = 0; i < 5; i++)       // 转动的起点
      for (int k = 1; k <= 9; k++) {  // 转动的幅度
        B = A;
        (B[i] += k) %= 10, M[B]++;                     // [i,i] += k
        if (i + 1 < 5) (B[i + 1] += k) %= 10, M[B]++;  // [i,i+1] += k;
      }
  }
  int ans = 0;
  for (auto p : M) ans += (!AS.count(p.first) and p.second == n);
  return printf("%d\n", ans), 0;
}
// AC 100

T2 消消乐

90分代码

// CSP-S 2023 密码锁
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main() {
#ifdef ONLINE_JUDGE
  freopen("game.in", "r", stdin);
  freopen("game.out", "w", stdout);
#endif
  int n;
  string A;
  cin >> n >> A;
  string stk;
  unordered_map<string, int> SM{{stk, 1}};
  LL ans = 0;
  for (char c : A) {
    if (!stk.empty() and stk.back() == c)
      stk.pop_back();
    else
      stk += c;
    ans += SM[stk], SM[stk]++;
  }
  return printf("%lld\n", ans), 0;
}
// AC 90

100分代码

// CSP-S 2023 消消乐
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
int main() {
#ifdef ONLINE_JUDGE
  freopen("game.in", "r", stdin);
  freopen("game.out", "w", stdout);
#endif
  int n;
  string A;
  cin >> n >> A;
  string stk;
  using ULL = unsigned long long;
  vector<ULL> R(n + 1);
  ULL P = 1e9 + 7;
  R[0] = 1;
  for (int i = 1; i <= n; i++) R[i] = R[i - 1] * P;  // Pⁱ
  unordered_map<ULL, int> HM{{0, 1}};  // 所有前缀消除之后的hash
  LL ans = 0, h = 0;
  for (char c : A) {
    if (!stk.empty() and stk.back() == c)      // 栈顶可以消除
      stk.pop_back(), h -= c * R[stk.size()];  // 消除并更新hash
    else
      h += c * R[stk.size()], stk += c;  // 入栈并更新hash
    ans += HM[h], HM[h]++;  // 更新区间个数,记录栈的状态
  }
  return printf("%lld\n", ans), 0;
}
// AC 100

T3 结构体

// CSP-S 2023 结构体
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct STInfo;
// 基础类型及其长度
map<string, int> MT{{"byte", 1}, {"short", 2}, {"int", 4}, {"long", 8}};
vector<STInfo> Ts;        // 所有的类型
map<string, int> TIDs;    // 类型名:id
struct STInfo {           // 结构体信息
  string name;            // 类型名
  LL align, size;         // 对齐要求, 大小
  vector<int> mTypes;     // 成员类型
  vector<string> mNames;  // 成员名称
  map<string, int> mId;   // 成员名称:编号
  vector<LL> m_st, m_ed;  // 每个成员占用内存的起始和结束地址
  STInfo() : align(0), size(0) {}
  void add_var(const string& t, const string& n) {  // 增加一个类型为t的成员n
    assert(TIDs.count(t));     // 类型t必须已经存在
    int ti = TIDs[t];
    auto& mt = Ts[ti];
    align = max(align, mt.align);  // 对齐要求等于其成员的对齐要求的最大值
    mId[n] = mNames.size();    // 成员名称对应的编号
    mNames.push_back(n), mTypes.push_back(ti);  // 成员名称类型
    LL st = m_ed.empty() ? 0 : m_ed.back();     // 新变量的起点
    while (st % mt.align) ++st;   // 起点要考虑对齐
    LL ed = st + mt.size;   // 终点不用考虑对齐
    m_st.push_back(st), m_ed.push_back(ed), size = ed;
    while (size % align) ++size;  // 整体大小考虑对齐
  }
  LL mem_addr(const string& m) const {  // 成员m的地址
    return m_st.at(mId.at(m));
  }
  int mem_type(const string& m) const {  // 成员m的类型
    return mTypes.at(mId.at(m));
  }
  int mid_of_addr(LL a) const {
    assert(a >= 0);
    int msz = m_st.size();  // 看看哪个成员包含了这个地址, 数据量不大
    for (int i = 0; i < msz; ++i)
      if (m_st[i] <= a && a < m_ed[i]) return i;
    return -1;
  }
};
STInfo G;    // 全局看做一个大结构体
void init() {      // 基础类型初始化
  for (auto p : MT) {  // byte,short,int,long
    string s = p.first;
    // 对于基本类型:对齐要求等于其占据空间大小, 并且没有成员
    STInfo si;
    si.name = s, si.align = MT[s], si.size = MT[s];
    si.m_st.push_back(0), si.m_ed.push_back(MT[s]);
    TIDs[s] = Ts.size(), Ts.push_back(si);
  }
  G.name = "root";
}
// 读入并添加一个类型
const STInfo& add_type() {
  int k;
  STInfo si;
  cin >> si.name >> k;  // 示类型名与成员数量,
  for (string t, n; k--;) cin >> t >> n, si.add_var(t, n);  // 添加成员
  TIDs[si.name] = Ts.size(), Ts.push_back(si);
  return Ts.back();
}
// 所有被定义的元素将按顺序,从内存地址为0开始依次排开
LL def_var(const string& type, const string& name) {
  return G.add_var(type, name), G.m_st.back();
}
// 如a.b.c,需要输出如上被访问的最内层元素的起始地址。
LL find_addr(string v) {
  replace(begin(v), end(v), '.', ' ');
  stringstream ss(v);
  vector<string> ns;
  for (string s; ss >> s; ns.push_back(s))
    ;
  assert(!ns.empty());
  LL a = G.mem_addr(ns[0]);  // 起始地址
  for (int i = 1, ti = G.mem_type(ns[0]); i < (int)ns.size(); i++) {
    a += Ts[ti].mem_addr(ns[i]);  // 成员的内存中的起始位置(偏移量)
    ti = Ts[ti].mem_type(ns[i]);  // 成员的类型, 进入下一级
  }
  return a;
}
string addr_type_name(LL a) {  // 找到addr对应的变量类型
  string s, er = "ERR";
  int mi = G.mid_of_addr(a);
  if (mi == -1) return er;
  s += G.mNames[mi], a -= G.m_st[mi];  // 进入下一级
  for (int ti = G.mTypes[mi]; !MT.count(Ts[ti].name);) {
    const auto& tp = Ts[ti];
    mi = tp.mid_of_addr(a);
    if (mi == -1) return er;
    s += '.' + tp.mNames[mi], a -= tp.m_st[mi], ti = tp.mTypes[mi];
  }
  return s;
}
int main() {
#ifdef ONLINE_JUDGE
  freopen("struct.in", "r", stdin);
  freopen("struct.out", "w", stdout);
#endif
  init();
  int T;
  cin >> T;
  string t, n, s;
  LL addr;
  for (int i = 0, op; i < T; i++) {
    cin >> op;
    if (op == 1) {
      const STInfo& tp = add_type();
      printf("%lld %lld\n", tp.size, tp.align);
    } else if (op == 2)  // 该元素的类型与名称
      cin >> t >> n, printf("%lld\n", def_var(t, n));
    else if (op == 3)
      cin >> s, printf("%lld\n", find_addr(s));
    else if (op == 4)
    cin >> addr, puts(addr_type_name(addr).c_str());
  }
  return 0;
}
// AC 100

T4 种树

// CSPS-2023 种树
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int NN = 1e5 + 4;
LL A[NN], B[NN], C[NN];
int N, F[NN];  // F[i] 表示i这个点最晚种树的天数
vector<int> G[NN];
void dfs(int u, int fa) {
  for (auto v : G[u])  // v一定比父亲u晚一天种
    if (v != fa) dfs(v, u), F[u] = min(F[u], F[v] - 1);
}
using BI = __int128;
// 要求点i在t天后达到目标(≥aᵢ),必须在第f天前开始种,返回f
LL solve_f(int i, const LL t) {
  LL x = 4e18, b = B[i], c = C[i];  // x树的高度的拐点
  if (c < 0) x = (b - 1 - c - 1) / -c - 1;  // 一开始递减, 第x+1天开始增长率=1
  LL l = 1, r = min(2LL * N, t) + 1;
  while (l + 1 < r) {
    LL m = (l + r) / 2;
    BI s = 0;   // x是拐点
    if (x > t)  // 直接计算从1到t(梯形面积)
      s = (BI)(b + c * m + b + c * t) * (t - m + 1) / 2;
    else if (x >= m)  // m到x, x+1到t两段, 梯形+矩形的面积
      s = (BI)(b + c * m + b + c * x) * (x - m + 1) / 2 + t - x;
    else  // x < m, 所以m到t一路增长率都是1
      s = t - m + 1;
    (s < A[i] ? r : l) = m;
  }
  return r;
}
bool check(LL t) {
  for (int i = 1; i <= N; i++) {
    LL f = solve_f(i, t);
    if (f == 1) return false;
    F[i] = f - 1;
  }
  dfs(1, 0);  // 父亲u还要考虑儿子v的种植时间要求(可能更早)
  sort(F + 1, F + N + 1);  // 按照最晚种植的要求从低到高排序
  for (int i = 1; i <= N; i++)
    if (F[i] < i) return false;  // 无法满足要求
  return true;
}
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  cin >> N;
  for (int i = 1; i <= N; i++) cin >> A[i] >> B[i] >> C[i];
  for (int i = 1, u, v; i < N; i++)
    cin >> u >> v, G[u].push_back(v), G[v].push_back(u);
  int l = N, r = 1e9;  // 保证r一直是合法解
  while (l + 1 < r) {
    int m = (l + r) / 2;
    (check(m) ? r : l) = m;
  }
  return printf("%d\n", r), 0;
}
// AC 100
转载于https://mp.weixin.qq.com/s/khSLl0KqpKu7vY1i-238OA
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇