• [LuoguP2161] 会场预约


    题目描述

    PP大厦有一间空的礼堂,可以为企业或者单位提供会议场地。这些会议中的大多数都需要连续几天的时间(个别的可能只需要一天),不过场地只有一个,所以不同的会议的时间申请不能够冲突。也就是说,前一个会议的结束日期必须在后一个会议的开始日期之前。所以,如果要接受一个新的场地预约申请,就必须拒绝掉与这个申请相冲突的预约。 一般来说,如果PP大厦方面事先已经接受了一个会场预约,例如从10日到15日,就不会在接受与之相冲突的预约,例如从12日到17日。不过,有时出于经济利益,PP大厦方面有时会为了接受一个新的会场预约,而拒绝掉一个甚至几个之前预订的预约。 于是,礼堂管理员QQ的笔记本上笔记本上经常记录着这样的信息: 本题中为方便起见,所有的日期都用一个整数表示。例如,如果一个为期10天的会议从“90日”开始到“99日”,那么下一个会议最早只能在“100日”开始。 最近,这个业务的工作量与日俱增,礼堂的管理员QQ希望参加SHTSC的你替他设计一套计算机系统,方便他的工作。这个系统应当能执行下面两个操作: A操作:有一个新的预约是从“start日”到“end日”,并且拒绝掉所有与它相冲突的预约。执行这个操作的时候,你的系统应当返回为了这个新预约而拒绝掉的预约个数,以方便QQ与自己的记录相校对。 B操作:请你的系统返回当前的仍然有效的预约的总数。


    形式化描述

    你需要维护一个 在数轴上的线段 的集合 SS,支持两种操作:

    • A l r 表示将 SS 中所有与线段 [l,r][l,r] 相交的线段删去,并将 [l,r][l,r] 加入 SS 中。
    • B 查询 SS 中的元素数量。

    对于 A 操作,每次还需输出删掉的元素个数。

    输入格式

    第一行一个正整数 nn,表示操作个数。
    接下来 nn 行,每行表示一个操作,都是上面两种中的一个。

    输出格式

    输出 nn 行,每行一个整数,表示对应操作的答案。

    输入输出样例

    输入 #1
    6
    A 10 15
    A 17 19
    A 12 17
    A 90 99
    A 11 12
    B
    输出 #1
    0
    0
    2
    0
    1
    2

    说明/提示

    【数据范围】
    对于 100\%100% 的数据,1le n le 2 imes 10^51n2×105,1le l le r le 10^51lr105。

     
    把线段扔到平衡树里,维护即可
    学习了一波fhq treap
    真是喵啊
     
    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200000 + 10;
    struct node{
        int l, r, pri, lc, rc, size;
        node(){
            size = 0;
        }
        node(int l, int r): l(l), r(r){
            pri = rand();
            lc = rc = 0;
            size = 1;
        }
    }tree[maxn];
    int tcnt = 0, root = 0;
    int newnode(int l, int r){
        tree[++tcnt] = node(l, r);
        return tcnt;
    }
    void update(int x){
        tree[x].size = tree[tree[x].lc].size + tree[tree[x].rc].size + 1;
    }
    void split_r(int x, int &a, int &b, int l){
        if(!x){
            a = b = 0;
            return;
        }
        if(tree[x].r < l){
            a = x;
            split_r(tree[x].rc, tree[a].rc, b, l);
        }
        else{
            b = x;
            split_r(tree[x].lc, a, tree[b].lc, l);
        }
        update(x);
    }
    void split_l(int x, int &a, int &b, int r){
        if(!x){
            a = b = 0;
            return;
        }
        if(tree[x].l <= r){
            a = x;
            split_l(tree[x].rc, tree[a].rc, b, r);
        }
        else{
            b = x;
            split_l(tree[x].lc, a, tree[b].lc, r);
        }
        update(x);
    }
    void merge(int &x, int a, int b){
        if(!a || !b){
            x = a | b;
            return;
        }
        if(tree[a].pri < tree[b].pri){
            x = a;
            merge(tree[a].rc, tree[a].rc, b);
        }
        else{
            x = b;
            merge(tree[b].lc, a, tree[b].lc);
        }
        update(x);
    }
    void insert(int l, int r){
        int a, b;
        split_r(root, a, b, l);
        merge(root, a, newnode(l, r));
        merge(root, root, b);
    
    }
    int main(){
        int n;
        cin >> n;
        char Q;
        int l, r, a, b, c;
        for(int i = 1; i <= n; i++){
            cin >> Q;
            if(Q == 'A'){
                cin >> l >> r;
                split_r(root, a, b, l);
                split_l(b, b, c, r);
                cout << tree[b].size << endl;
                merge(root, a, c);
                insert(l, r);
            }
            else{
                cout << tree[root].size << endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    680C. Bear and Prime 100 数学
    Codeforces 681C. Heap Operations 优先队列
    Codeforces C. NP-Hard Problem 搜索
    Codeforces 689C. Mike and Chocolate Thieves 二分
    Codeforces 689B. Mike and Shortcuts SPFA/搜索
    Codeforces Round #223 (Div. 2) E. Sereja and Brackets 线段树区间合并
    Educational Codeforces Round 1 E. Chocolate Bar dp
    Testing Round #12 A,B,C 讨论,贪心,树状数组优化dp
    Educational Codeforces Round 2 E. Lomsat gelral 启发式合并map
    hdu 3706 Second My Problem First 单调队列
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/12107304.html
Copyright © 2020-2023  润新知