首页 > 其他分享 >P11236 「KTSC 2024 R1」水果游戏 题解

P11236 「KTSC 2024 R1」水果游戏 题解

时间:2024-11-05 16:57:53浏览次数:1  
标签:KTSC int 题解 P11236 back second cr ns first

很有意思的一道题。

思路

首先将相邻一样的数合并,每个元素变成一个二元组,表示数与出现次数。

考虑什么时候不能合并。

我们发现假如充分合并后,现在有连续的三个数 \(x_1,x_2,x_3\),以及他们各自的出现次数 \(y_1,y_2,y_3\)。

如果 \(x_1>x_2,x_3>x_2\)。

我们想要合并这三个,必须要先把 \(x_2\) 合并成 \(\min(x_1,x_3)\)。

但是如果做不到的话,那么这三个数就一定不可能合并了。

相当于整个序列从这里断开了。

这样的话,整个序列是一堆单峰序列。

考虑末尾追加一个二元组 \((x,y)\) 会有什么影响:

  1. 序列尾部元素与 \(x\) 相等。

    累加 \(y\) 即可。

  2. 序列元素少于两个。

    直接插入即可。

  3. 序列尾部大于 \(x\), 或尾部大于倒数第二个。

    同样直接插入即可。

  4. 除了以上情况,我们就需要一些处理了。

    将末尾与倒数第二个提出来,记为 \((x_1,y_1),(x_2,y_2)\)。

    首先我们判断能否将 \(x_1\) 提升至 \(\min(x,x_2)\),如果可以,我们就先将其提升,然后再递归插入。

    如果不可以,我们可以插入一个极大值作为分割符,然后将 \(x_1\) 的贡献往 \(x\) 与 \(x_2\) 上累加,再递归插入。

线段树维护即可。

时间复杂度:\(O(nv\log n)\)。

Code

#include <bits/stdc++.h>
using namespace std;

int n;
int a[100010];
struct Node {
  int ns = 0;
  vector<pair<int, int>> cr{};
  inline void init(int x) { vector<pair<int, int>>{{x, 1}}.swap(cr); ns = x; }
  inline void add(pair<int, int> x) {
    if (x.second) ns = max(ns, x.first + __lg(x.second));
    if (cr.size() && cr.back().first == x.first) {
      cr.back().second += x.second;
      if (cr.back().second)
        ns = max(ns, cr.back().first + __lg(cr.back().second));
    }
    else if (cr.size() <= 1)
      cr.push_back(x);
    else if (cr.back().first > x.first)
      cr.push_back(x);
    else if (cr.size() >= 2 && cr.back().first > cr[cr.size() - 2].first)
      cr.push_back(x);
    else {
      auto y = cr.back();
      cr.pop_back();
      auto z = cr.back();
      int d = min(30, min(x.first, z.first) - y.first);
      if ((y.second & (-y.second)) >= (1 << d))
        add({y.first + d, y.second >> d}), add(x);
      else {
        if (__lg(y.second) >= z.first - y.first)
          add({z.first, y.second >> (z.first - y.first)});
        add({1e9, 0});
        if (__lg(y.second) >= x.first - y.first)
          x.second += y.second >> (x.first - y.first);
        add(x);
      }
    }
  }
  inline friend Node operator+(Node a, Node b) {
    Node c = a;
    c.ns = max(b.ns, c.ns);
    for (auto i : b.cr) c.add(i);
    return c;
  }
} ns, d[200010];

inline void build(int p, int l, int r) {
  if (l == r) d[p].init(a[l]);
  else {
    int mid = (l + r) >> 1;
    build(mid<<1, l, mid);
    build(mid<<1|1, mid + 1, r);
    d[p] = d[mid<<1] + d[mid<<1|1];
  }
}
inline void upd(int p, int l, int r, int k) {
  if (l == r) d[p].init(a[l]);
  else {
    int mid = (l + r) >> 1;
    if (mid >= k) upd(mid<<1, l, mid, k); else upd(mid<<1|1, mid + 1, r, k);
    d[p] = d[mid<<1] + d[mid<<1|1];
  }
}
inline void ask(int p, int l, int r, int L, int R) {
  if (L <= l && r <= R) ns = ns + d[p];
  else {
    int mid = (l + r) >> 1;
    if (L <= mid) ask(mid<<1, l, mid, L, R);
    if (mid <  R) ask(mid<<1|1, mid + 1, r, L, R);
  }
}
void prepare_game(vector<int> A) {
  n = A.size();
  for (int i = 1; i <= n; i++) a[i] = A[i - 1];
  build(1, 1, n);
}
int play_game(int l, int r) {
  ns.cr.clear();
  ns.ns = 0;
  ns.add({1e9, 0});
  ask(1, 1, n, l + 1, r + 1);
  ns.add({1e9, 0});
  return ns.ns;
}
void update_game(int p, int v) {
  a[p + 1] = v;
  upd(1, 1, n, p + 1);
}

标签:KTSC,int,题解,P11236,back,second,cr,ns,first
From: https://www.cnblogs.com/JiaY19/p/18528332

相关文章

  • xss-labs题解
    xss—labsxss—labslevel1(GET型)level2(闭合)level3(htmlspecialchars绕过)level4(左右尖括号过滤)level5(a标签法)level6(大小写绕过)level7(双写绕过)level8(利用href自动Unicode解码特性)level9(注释绕过后端判断)xss—labs题目链接BUUCTF在线评测题目源码xss-lab/lev......
  • CSP-J2024题解
    前言J组本来可以AK的,但是对于DP的敏感度太低了,导致T4赛时没有往DP上面想。正片T1:扑克牌题目描述小P从同学小Q那儿借来一副\(n\)张牌的扑克牌。本题中我们不考虑大小王,此时每张牌具有两个属性:花色和点数。花色共有\(4\)种:方片、草花、红桃和黑桃。点数共......
  • 题解 P11231【[CSP-S 2024] 决斗】
    题目描述今天是小Q的生日,他得到了\(n\)张卡牌作为礼物。这些卡牌属于火爆的“决斗怪兽”,其中,第\(i\)张卡代表一只攻击力为\(r_i\),防御力也为\(r_i\)的怪兽。一场游戏分为若干回合。每回合,小Q会选择某只怪兽\(i\)以及另一只怪兽\(j(i\neqj)\),并让怪兽\(i\)向怪......
  • 题解 P11232【[CSP-S 2024] 超速检测】
    题目描述小D新入职了某国的交管部门,他的第一个任务是负责国家的一条长度为\(L\)的南北主干道的车辆超速检测。为了考考小D,上司首先需要他解决一个简化的场景。这个周末,主干道上预计出现\(n\)辆车,其中第\(i\)辆车从主干道上距离最南端\(d_i\)的位置驶入,以\(v_i\)的......
  • 题解 P11233【[CSP-S 2024] 染色】
    题目描述给定一个长度为\(n\)的正整数数组\(A\),其中所有数从左至右排成一排。你需要将\(A\)中的每个数染成红色或蓝色之一,然后按如下方式计算最终得分:设\(C\)为长度为\(n\)的整数数组,对于\(A\)中的每个数\(A_i\)(\(1\leqi\leqn\)):如果\(A_i\)左侧没有与其同......
  • 牛客周赛 Round 66 题解
    牛客周赛Round66题解牛客周赛Round66A-小苯吃糖果_牛客周赛Round66#include<bits/stdc++.h>#defineendl'\n'usingnamespacestd;inta[5];voidsolve(){ for(inti=1;i<=3;i++)cin>>a[i]; sort(a+1,a+4); intans=max(a[1]+a[2],a[3]); cout<......
  • Codeforces Round 983 (Div. 2) 10.31 ABC题解
    CodeforcesRound983(Div.2)10.31题解A.Circuit数学(math)贪心(greedy)模拟(implementation)题意:有\(n\)盏灯,对应\(2\astn\)个开关,即每盏灯对应两个开关,开关打开或者关闭用\(1\)和\(0\)表示。给出\(2\astn\)个开关的状态,需要求解出可能开灯的最小数量和最大数量。......
  • [JRKSJ R2] 你的名字。题解
    [JRKSJR2]你的名字。卡常题,根号分治。卡了三页。以下记\(V=\max\{a_i\}\)考虑当\(k\le\sqrtV\)时,对于每一个\(k\),写个ST表/线段树/分块即可,实测分块最快。复杂度分别为\(O(n\logn)+O(q)+O(n\logn)\qquadO(n)+O(q\logn)+O(n)\qquadO(n)+O(q\sqrtn)+O(n)\)。当\(k>\sq......
  • [PA2024] Modernizacja Bajtocji 题解
    DescriptionByteland正在走向现代化。最新的政府项目旨在为那些没有电脑的村镇居民提供电脑。Byteasar正在监督该计划中的一个村庄——Bytetown——的现代化进程,目前那里没有一个居民拥有电脑。Bytetown有\(n\)个居民,为了简单起见,Byteasar将他们用\(1\)到\(n\)的整数......
  • Codeforces Round 984 (Div. 3) 题解
    CodeforcesRound984(Div.3)题解CodeforcesRound984(Div.3)Problem-A-Codeforces解题思路n很小,直接枚举即可#include<bits/stdc++.h>#defineendl'\n'usingnamespacestd;inta[100];voidsolve(){ intn;cin>>n; for(inti=1;i<=n;i......