zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    2021-04-02:给定一个正方形或者长方形矩阵matrix,实现zigzag打印。[[0,1,2],[3,4,5],[6,7,8]]的打印顺序是0,1,3,6,4,2,5,7,8。
    2021-04-01:给定一个正方形矩阵matrix,原地调整成顺时针90度转动的样子。[[a,b,c],[d,e,f],[g,h,i]]变成[[g,d,a],[h,e,b],[i,f,c]]。
    2021-03-31:给定一个数组arr,给定一个值v。求子数组平均值小于等于v的最长子数组长度。
    2021-03-30:给定一个整数组成的无序数组arr,值可能正、可能负、可能0。给定一个整数值K,找到arr的所有子数组里,哪个子数组的累加和<=K,并且是长度最大的。返回其长度。
    2021-03-29:无序数组arr,子数组-1和1的数量一样多,请问最长子数组的长度是多少?
    04Null和Undefined
    03数据类型
    win10 命令行下 重启虚拟网卡
    JavaScript注释及命名规范
    第一个javascrpt代码
  • 原文地址:https://www.cnblogs.com/ruoruoruo/p/12107304.html
Copyright © 2011-2022 走看看