首页 > 其他分享 >CF1858E1 做题笔记

CF1858E1 做题笔记

时间:2023-09-18 22:14:25浏览次数:52  
标签:cnt int res 1000005 笔记 CF1858E1 操作 op

题目链接

赛时没做出来,晚上补了一下,发现是一种很好玩的 数据结构。

由于可以离线又要支持删除后 $k$ 个又要支持撤销操作,不会写主席树只能选择操作树。

对序列按照时间建成一颗操作树,处于某个点的回合时,这个序列的样子就是它以及它的祖先。

来依次考虑某个操作,设当前是序列的末尾是 $p$ 号元素。

加操作,直接在 $p$ 下面挂一个儿子,然后 $p$ 变成它即可。

减操作,此时我们发现需要跳 $k$ 级祖先,就需要倍增了,这个操作于是解决。

撤销操作,其实可以实时记录加减操作的一个栈,这个时候把栈顶弹出,把 $p$ 变成现在的栈顶即可。

询问操作,留到最后建完表达式树再做。

我们发现询问就是问每个点向上构成的序列中的元素个数,可以用类似莫队的方法解决,但是这一部分是 $O(n)$ 的,于是就过了,代码:

#include <bits/stdc++.h>
#define For(i, a, b) for (int i = (a); i <= (b); i ++)
#define foR(i, a, b) for (int i = (a); i >= (b); i --)
using namespace std;
stack <int> st;
int p, q, x, cnt, res;
int f[1000005][20], val[1000005];
int b[1000005], ans[1000005], pos[1000005];
char op[1000005];
vector <int> G[1000005];
void add (int x) {
    b[x] ++;
    if (b[x] == 1) ++ res;
}
void rem (int x) {
    b[x] --;
    if (b[x] == 0) -- res;
}
void dfs (int u) {
    if (u) add (val[u]);
    ans[u] = res;
    for (int v : G[u]) dfs (v);
    if (u) rem (val[u]);
}
signed main () {
    st.push (0);
    scanf ("%d", &q);
    For (i, 1, q) {
        op[i] = getchar ();
        while (op[i] == ' ' || op[i] == '\n') op[i] = getchar ();
        if (op[i] == '+') {
            scanf ("%d", &x);
            f[++ cnt][0] = p;
            val[cnt] = x;
            For (j, 1, 20) f[cnt][j] = f[f[cnt][j - 1] ][j - 1];
            p = cnt;
        } else if (op[i] == '-') {
            scanf ("%d", &x);
            foR (j, 20, 0) {
                if (x >= (1 << j) ) {
                    x -= (1 << j);
                    p = f[p][j];
                }
            }
        } else if (op[i] == '!') {
            st.pop ();
            p = st.top ();
        }
        pos[i] = p;
        if (op[i] != '?' && op[i] != '!') st.push (p);
    }
    For (i, 1, cnt) G[f[i][0] ].push_back (i);
    dfs (0);
    For (i, 1, q) if (op[i] == '?') cout << ans[pos[i] ] << '\n';
    return 0;
}

 

标签:cnt,int,res,1000005,笔记,CF1858E1,操作,op
From: https://www.cnblogs.com/Xy-top/p/17713204.html

相关文章

  • 关于`dial unix /var/run/docker.sock: connect: permission denied`的处理方法笔记
    之前遇到的一个问题,使用非root用户时操作docker提示无权限,在查阅了一些文章之后自己又摸索出了一些更方便的方法,顺手记录下来。一、问题发现根据报错信息dialunix/var/run/docker.sock:connect:permissiondenied,可以看出,是因为当前用户对docker使用的unixdomainsocket......
  • qemu源码分析(6)--Apple的学习笔记
    一,前言由于看到了类似的写法,都用到了object_dynamic_cast_assert函数,所以分析下。二,源码分析看到如下代码的写法,很眼熟CortexMBoardState*board=CORTEXM_BOARD_STATE(machine);machine的类型是MachineState*#defineCORTEXM_BOARD_STATE(obj)\OBJECT_CHECK(CortexMBoardSt......
  • HTML笔记
    一、HTML基础1、网页文件、以.html或者.htm为后缀名的文件。2、网站网页的集合。3、HTML:超文本标记语言。纯文本(字符、数字、字母等)超文本:超越文本的限制、显示视频、音频、图片、动画等。超链接跳转功能。标记:打标记符号(字母、数字等组合),浏览器解析标记。4、工具的使用(1)插入HTML......
  • Python学习笔记
    Python语言是一种解释性、面向对象、动态数据类型的高级程序设计语言创始人:吉多,荷兰人时间:1989编写的,1991公开发行Python语言特点开源、免费面向过程、面向对象、交互式编程面向过程:以事情或解决问题的过程为中心,主要考虑解决问题的思路和步骤面向对象:以事务为中心,主要考虑解决问......
  • 数论——欧几里得算法和扩展欧几里得算法 学习笔记
    数论——欧几里得算法和扩展欧几里得算法引入最大公约数最大公约数即为GreatestCommonDivisor,常缩写为gcd。一组整数的公约数,是指同时是这组数中每一个数的约数的数。\(\pm1\)是任意一组整数的公约数;一组整数的最大公约数,是指所有公约数里面最大的一个。最小公倍数最......
  • openGauss学习笔记-73 openGauss 数据库管理-创建和管理索引
    openGauss学习笔记-73openGauss数据库管理-创建和管理索引73.1背景信息索引可以提高数据的访问速度,但同时也增加了插入、更新和删除操作的处理时间。所以是否要为表增加索引,索引建立在哪些字段上,是创建索引前必须要考虑的问题。需要分析应用程序的业务处理、数据使用、经常被......
  • git学习笔记
    git学习参考链接:https://www.bilibili.com/video/BV1MU4y1Y7h5获取本地仓库本地创建一个空目录作为本地git仓库。在这个目录的终端中执行gitinit,成功的话可以看到里面有一个.git文件夹工作流程工作区(workspace)--->暂存区(index)--->仓库(repository)工作区:修改已有文件(未暂......
  • ue4.26学习笔记1-角色移动
    ue4.26学习笔记1-角色移动角色旋转首先创建character蓝图类打开创建的蓝图类,为骨骼网格体添加模型,此处使用小白人的模型,然后添加弹簧臂组件和摄像机组件在项目设置->输入中添加鼠标x轴和y轴的操作映射,此处x轴操作映射命名为鼠标左右移动,y轴操作映射命名为鼠标上下移动,其中x......
  • 大三落汤狗の算法笔记 (持续更新)
    1.算法复杂度分析简便:复杂度取阶数最高项,去系数。如:O(3n²+2n+1)=O(n²)O()低阶/o(),Ω()高阶/w(),θ()同阶阶关系成立:自反OΩθ/对称θ/传递OoΩwθO(f)+O(g)=O(max(f,g))O(f)+O(O(f))=O(f)O(递归)迭代法:n次计算,每次O(单次)求和eg:求n!求退出条件:T(1)=1求递推公式:T(n......
  • 《LINUX驱动程序设计》学习笔记 ——04
    1.模块的装载竞争(竞态)竞态是驱动程序设计极其重要的方面,始终要铭记:在注册完成后,内核的某些部分可能会立即使用我们刚刚注册的任何设施。换句话说,在初始化函数还在运行的时候,内核就完全可能会调用我们的模块。因此,在首次注册完成后,代码就应该准备好被内核其他部分调用;在用来......