首页 > 其他分享 >H. Ksyusha and the Loaded Set

H. Ksyusha and the Loaded Set

时间:2024-08-16 18:48:28浏览次数:10  
标签:10 set int tr Ksyusha le Set Loaded mathrm

H. Ksyusha and the Loaded Set

Ksyusha decided to start a game development company. To stand out among competitors and achieve success, she decided to write her own game engine. The engine must support a set initially consisting of $n$ distinct integers $a_1, a_2, \ldots, a_n$.

The set will undergo $m$ operations sequentially. The operations can be of the following types:

  • Insert element $x$ into the set;
  • Remove element $x$ from the set;
  • Report the $k$-load of the set.

The $k$-load of the set is defined as the minimum positive integer $d$ such that the integers $d, d + 1, \ldots, d + (k - 1)$ do not appear in this set. For example, the $3$-load of the set $\{3, 4, 6, 11\}$ is $7$, since the integers $7, 8, 9$ are absent from the set, and no smaller value fits.

Ksyusha is busy with management tasks, so you will have to write the engine. Implement efficient support for the described operations.

Input

The first line contains an integer $t$ ($1 \le t \le 10^4$) — the number of test cases.

The following lines describe the test cases.

The first line contains an integer $n$ ($1 \le n \le 2 \cdot 10^5$) — the initial size of the set.

The second line contains $n$ integers $a_1, a_2, \ldots, a_n$ ($1 \le a_1 < a_2 < \ldots < a_n \le 2 \cdot 10^6$) — the initial state of the set.

The third line contains an integer $m$ ($1 \le m \le 2 \cdot 10^5$) — the number of operations.

The next $m$ lines contain the operations. The operations are given in the following format:

  • + $x$ ($1 \le x \le 2 \cdot 10^6$) — insert element $x$ into the set (it is guaranteed that $x$ is not in the set);
  • - $x$ ($1 \le x \le 2 \cdot 10^6$) — remove element $x$ from the set (it is guaranteed that $x$ is in the set);
  • ? $k$ ($1 \le k \le 2 \cdot 10^6$) — output the value of the $k$-load of the set.

It is guaranteed that the sum of $n$ across all test cases does not exceed $2 \cdot 10^5$, and the same holds for $m$.

Output

For each test case, output the answers to the operations of type "?".

Example

Input

3
5
1 2 5 905 2000000
15
- 2
? 2
? 1
- 1
? 1
+ 4
+ 2
? 2
+ 6
- 4
+ 7
? 2
? 3
? 4
? 2000000
5
3 4 5 6 8
9
? 5
- 5
? 5
+ 1
? 2
- 6
- 8
+ 6
? 5
5
6 7 8 9 10
10
? 5
- 6
? 4
- 10
+ 5
- 8
+ 3
+ 2
- 3
+ 10

Output

2 2 1 6 3 8 8 2000001 
9 9 9 7 
1 1 

 

解题思路

  和这题 P2894 [USACO08FEB] Hotel G 几乎一样。

  把插入 $x$ 看成在下标 $x$ 处出置为 $1$,移除 $x$ 就置为 $0$,询问就相当于在 $1 \sim 4 \cdot 10^6$ 中查询长度至少为 $k$ 的连续一段 $0$ 的最小左端点。所有的修改操作都可以用线段树进行维护,询问操作则对线段树进行二分。

  先定义线段树节点:

struct Node {
    int l, r; // 维护区间的左右端点
    int len;  // 区间长度
    int ls;   // 区间左端点起往右连续一段0的长度
    int rs;   // 区间右端点起往左连续一段0的长度
    int s;    // 整个区间连续一段0的最大长度
}tr[N * 4];

  考虑 pushup 操作,假设要更新的节点 $u$ 的左右儿子分别是 $l$ 和 $r$。显然有 $u\mathrm{.ls} = l\mathrm{.ls}$,如果左儿子维护的区间全是 $0$,即 $l\mathrm{.ls} = l\mathrm{.len}$,那么还需要加上 $r\mathrm{.ls}$。同理有 $u\mathrm{.rs} = r\mathrm{.rs}$,如果右儿子维护的区间全是 $0$ 还要加上 $l\mathrm{.rs}$。最后是 $u\mathrm{.s}$,把分成三种情况,整段 $0$ 都在左儿子,该情况最长的一段 $0$ 是 $l\mathrm{.s}$;整段 $0$ 都在右儿子,该情况最长的一段 $0$ 是 $r\mathrm{.s}$;整段 $0$ 横跨左右儿子,该情况最长的一段 $0$ 是 $l\mathrm{.rs} + r\mathrm{.ls}$。

void pushup(int u) {
    tr[u].ls = tr[u << 1].ls + (tr[u << 1].s == tr[u << 1].len) * tr[u << 1 | 1].ls;
    tr[u].rs = tr[u << 1 | 1].rs + (tr[u << 1 | 1].s == tr[u << 1 | 1].len) * tr[u << 1].rs;
    tr[u].s = max({tr[u << 1].s, tr[u << 1 | 1].s, tr[u << 1].rs + tr[u << 1 | 1].ls});
}

  修改操作就是基本的单点修改,其中如果要将下标 $x$ 置为 $c$,那么需要把维护该位置的节点的信息都置为 $\neg c$:

void modify(int u, int x, int c) {
    if (tr[u].l == tr[u].r) {
        tr[u].ls = tr[u].rs = tr[u].s = tr[u].len * !c;
    }
    else {
        int mid = tr[u].l + tr[u].r >> 1;
        if (x <= mid) modify(u << 1, x, c);
        else modify(u << 1 | 1, x, c);
        pushup(u);
    }
}

  最后是查询操作,因为要找到满足条件的最小的下标,因此先看看当前节点的左儿子 $l$ 是否存在长度至少为 $k$ 的一段 $0$,如果存在则递归到 $l$。否则看看横跨左右儿子的一段 $0$ 的长度是否至少为 $k$,如果满足则直接回传 $l\mathrm{.r} - l\mathrm{.rs} + 1$。最后再看看右儿子 $r$ 是否存在长度至少为 $k$ 的一段 $0$,存在则递归到 $r$(一定存在,因为维护的值域最大设到了 $4 \cdot 10^6$)。

int query(int u, int k) {
    if (tr[u].l == tr[u].r) return tr[u].l;
    if (tr[u << 1].s >= k) return query(u << 1, k);
    if (tr[u << 1].rs + tr[u << 1 | 1].ls >= k) return tr[u << 1].r - tr[u << 1].rs + 1;
    if (tr[u << 1 | 1].s >= k) return query(u << 1 | 1, k);
    return 0;
}

  AC 代码如下,时间复杂度为 $O((n+m) \log{A})$:

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

typedef long long LL;

const int N = 4e6 + 5;

struct Node {
    int l, r, len, ls, rs, s;
}tr[N * 4];

void pushup(int u) {
    tr[u].ls = tr[u << 1].ls + (tr[u << 1].s == tr[u << 1].len) * tr[u << 1 | 1].ls;
    tr[u].rs = tr[u << 1 | 1].rs + (tr[u << 1 | 1].s == tr[u << 1 | 1].len) * tr[u << 1].rs;
    tr[u].s = max({tr[u << 1].s, tr[u << 1 | 1].s, tr[u << 1].rs + tr[u << 1 | 1].ls});
}

void build(int u, int l, int r) {
    tr[u] = {l, r, r - l + 1};
    if (l == r) {
        tr[u].ls = tr[u].rs = tr[u].s = 1;
    }
    else {
        int mid = l + r >> 1;
        build(u << 1, l, mid);
        build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

void modify(int u, int x, int c) {
    if (tr[u].l == tr[u].r) {
        tr[u].ls = tr[u].rs = tr[u].s = tr[u].len * !c;
    }
    else {
        int mid = tr[u].l + tr[u].r >> 1;
        if (x <= mid) modify(u << 1, x, c);
        else modify(u << 1 | 1, x, c);
        pushup(u);
    }
}

int query(int u, int k) {
    if (tr[u].l == tr[u].r) return tr[u].l;
    if (tr[u << 1].s >= k) return query(u << 1, k);
    if (tr[u << 1].rs + tr[u << 1 | 1].ls >= k) return tr[u << 1].r - tr[u << 1].rs + 1;
    if (tr[u << 1 | 1].s >= k) return query(u << 1 | 1, k);
    return 0;
}

void solve() {
    int n, m;
    cin >> n;
    set<int> st;
    while (n--) {
        int x;
        cin >> x;
        st.insert(x);
        modify(1, x, 1);
    }
    cin >> m;
    while (m--) {
        char op;
        int x;
        cin >> op >> x;
        if (op == '+') {
            st.insert(x);
            modify(1, x, 1);
        }
        else if (op == '-') {
            st.erase(x);
            modify(1, x, 0);
        }
        else {
            cout << query(1, x) << ' ';
        }
    }
    for (auto &x : st) {
        modify(1, x, 0);
    }
    cout << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    build(1, 1, N - 1);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Codeforces Round 966 (Div. 3) A - H:https://zhuanlan.zhihu.com/p/714360692

标签:10,set,int,tr,Ksyusha,le,Set,Loaded,mathrm
From: https://www.cnblogs.com/onlyblues/p/18363455

相关文章

  • 【C++的剃刀】我不允许你还不会map和set
     ​ 学习编程就得循环渐进,扎实基础,勿在浮沙筑高台   循环渐进Forward-CSDN博客Hello,这里是kiki,今天继续更新C++部分,我们继续来扩充我们的知识面,我希望能努力把抽象繁多的知识讲的生动又通俗易懂,今天要讲的是C++的map和set~目录 循环渐进Forward-CSDN博客关......
  • Spring DI 简单演示三层架构——Setter 注入
    SpringIOC的常见注入方法有3种:Setter注入、构造注入和属性注入。想了解更多可点击链接:Spring注入、注解以及相关内容补充        属性注入 不推荐。原因:使用私有的成员属性变量,依靠反射实现,破坏封装,只能依靠IOC容器实现注入,不严谨。所以我只演示Setter注入和构......
  • vue-router,vue3介绍,vue3快速创建项目,常用api,生命周期,setup的特殊写法
    Ⅰvue-router【一】路由守卫#1路由守卫是什么 是否登录,登录后才能访问,没登录重定向到login作用:对路由进行权限控制#2全局守卫、独享守卫、组件内守卫使用importElementfrom'element-ui'//全局路由守卫-->前置路由守卫router.beforeEach((to,fr......
  • Redis数据结构:动态字符串SDS、Intset、Dict详解
    动态字符串:我们都知道Redis中保存的Key是字符串,value往往是字符串或者字符串的集合。可见字符串是Redis中最常用的一种数据结构。不过Redis没有直接使用C语言中的字符串,因为C语言字符串存在很多问题:获取字符串长度的需要通过运算非二进制安全不可修改Redis构建了一种新的......
  • Getter访问器和Settter修改器
    7.3Getter访问器和Settter修改器目录7.3Getter访问器和Settter修改器7.3.1为什么需要Getter与Setter方法?7.3.2getter与setter方法7.3.3getter与setter的定义1、getter方法2、setter方法7.3.1为什么需要Getter与Setter方法?在Java中,类的属性通常被声明为私有的(private),以确......
  • 【数据结构】TreeMap和TreeSet
    目录前言TreeMap实现的接口内部类常用方法TreeSet实现的接口常用方法前言Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关。一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对。......
  • superset定制化配置修改总结
    1.需要想用iframe引入dashboard时, URL参数可用于修改仪表板的呈现方式,standalone=0属性枚举描述standalone0仪表盘正常显示1顶部导航已隐藏2顶部导航+标题被隐藏3顶部导航+标题+顶级标签被隐藏show_filters0渲染没有过滤栏的仪表板1(默认):如果启用了本机过滤器,则使用过......
  • Superset Docker-Compose部署
    bi系统是一类旨在帮助企业和组织分析、可视化和理解其业务数据的软件工具之前了解过商业的阿里quickbi,腾讯bi,开源的话用superset,据了解新老公司不少会调研supersethttps://github.com/apache/superset/releases/tag/4.0.2这里我使用了最新的包,经过测试发现一年前的镜像更新到......
  • ollama的set parameter的参数的注解
    >>>/setparameterAvailableParameters:/setparameterseed<int>Randomnumberseed/setparameternum_predict<int>Maxnumberoftokenstopredict/setparametertop_k<int>Pickfromtopk......
  • .Net Core appsettings.json详解 (多环境配置)
    前言在实际开发中一般分为开发环境与生产环境,不同环境下部分配置会有所不同,例如数据库连接字符串等。.NetCore框架中提供了三个值,Development(开发),Staging(分阶段),Production(生产环境),可以根据这三个值配置不同环境。创建appsettings文件创建项目时系统默认创建appsettin......