LuoguP2161 [SHOI2009]会场预约

Posted henry-1202

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LuoguP2161 [SHOI2009]会场预约相关的知识,希望对你有一定的参考价值。

题目地址

题目链接

题解

用fhqtreap对区间进行维护。

可以注意到的是,对于当前存在的预约,他们一定是升序排列的(有重叠的都被删了)。

那么就可以用按照位置分裂的fhqtreap搞了(预约无论按l还是按r都必定是升序的)。

每次插入一个区间的时候,就直接找出互不重叠的前驱和后继,那么需要删除的就是中间的那一段了(因为区间升序),对于每一个A的答案就是中间那段的siz,合并的时候注意一下顺序就好,别把顺序颠倒了(无论是merge还是split)。

对于B询问,答案就是root的siz。

#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#define ll long long
using namespace std;

const int N = 200010;

struct task { int l, r; };
struct fhq { int l, r, siz, rnd; task v; }t[N];
int tot, root;

#define lc (t[rt].l)
#define rc (t[rt].r)
void up(int rt) { t[rt].siz = t[lc].siz + t[rc].siz + 1; } 
void split(int rt, int &l, int &r, int k) {
    if(!k) l = 0, r = rt;
    else if(t[rt].siz == k) l = rt, r = 0;
    else if(k <= t[lc].siz) r = rt, split(lc, l, lc, k), up(rt);
    else l = rt, split(rc, rc, r, k - t[lc].siz - 1), up(rt);
}
void merge(int &rt, int l, int r) {
    if(!l || !r) rt = l + r;
    else if(t[l].rnd < t[r].rnd) rt = l, merge(rc, rc, r), up(rt);
    else rt = r, merge(lc, l, lc), up(rt);
}
int pre(int rt, task a) {
    if(!rt) return 0;
    if(t[rt].v.r < a.l) return pre(rc, a) + t[lc].siz + 1;
    else return pre(lc, a);
}
int nxt(int rt, task a) {
    if(!rt) return 0;
    if(t[rt].v.l > a.r) return nxt(lc, a);
    else return nxt(rc, a) + t[lc].siz + 1;
}
int new_node(task a) {
    t[++tot].v = a;
    t[tot].siz = 1;
    t[tot].rnd = rand()<<15|rand();
    t[tot].l = t[tot].r = 0;
    return tot;
}
int build(task a) {
    int l = pre(root, a), r = nxt(root, a), x, y, z, k;
    split(root, x, y, r); split(x, z, k, l);
    int ans = t[k].siz, t = new_node(a);
    merge(t, z, t); merge(root, t, y); return ans;
}
#undef lc
#undef rc

int main() {
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("t.out","w",stdout);
#endif
    srand((unsigned)time(0));
    int T; task a; char ch[10];
    scanf("%d", &T);
    while(T--) {
        scanf("%s", ch);
        if(ch[0] == 'A') scanf("%d%d", &a.l, &a.r), printf("%d
", build(a));
        else printf("%d
", t[root].siz);
    }
    return 0;
}

以上是关于LuoguP2161 [SHOI2009]会场预约的主要内容,如果未能解决你的问题,请参考以下文章

P2161 [SHOI2009]会场预约

P2161 [SHOI2009]会场预约 - 线段树染色

[SHOI2009]Booking 会场预约

[SHOI 2009] 会场预约

[SHOI2009]会场预约

SHOI 2009 会场预约 平衡树 STL练习