题目描述

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

输入输出格式
输入格式:
输入文件的第一行是一个整数n,表示你的系统将接受的操作总数。 接下去n行每行表示一个操作。每一行的格式为下面两者之一: “A start end”表示一个A操作; “B”表示一个B操作。

输出格式:
输出文件有n行,每行一次对应一个输入。表示你的系统对于该操作的返回值。

输入输出样例
输入样例#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
说明
N< = 200000

1< = Start End < = 100000

线段树解法

把不同 任务当作颜色看待
线段树维护这区间是上面颜色管理 同时我们认为 这一区间超过一种颜色 用 -1 标记 0 表示没有被覆盖 大于0表示这一区间有第几个出现的任务颜色管理

在pushup 时 有

  1. if (tree[rt<<1] == tree[rt<<1|1]) tree[rt] = tree[rt<<1];
  2. else if (!tree[rt<<1] || !tree[rt<<1|1]) tree[rt] = tree[rt<<1] + tree[rt<<1|1];// 有个子树是0的话 直接拿另一个标记
  3. else tree[rt] = -1; // 区间颜色不同时 -1

所以对于A操作,我们只需要在线段树上查询询问的区间[x,y],并在查询的时候在全局开数组,记录一下有哪几个颜色(记得处理过的颜色标记一下,因为颜色只会出现一次,不需要也不能重复删除)。
会重复删也是因为lazy 0 是无色 都是 0的时候补下推 导致一些区间地下没有更新 所以vis去个重 防止减多

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, N = 1e5;

int x[maxn], y[maxn];
int que[maxn], tail,cnt;
bool vis[maxn];
int n, sum = 0;

int tree[maxn<<2], lazy[maxn<<2];

void pushup(int rt) {
    if (tree[rt<<1] == tree[rt<<1|1]) tree[rt] = tree[rt<<1];
    else if (!tree[rt<<1] || !tree[rt<<1|1]) tree[rt] = tree[rt<<1] + tree[rt<<1|1];
    else tree[rt] = -1;
}

void pushdown(int rt) {
    if (lazy[rt]) {
        tree[rt<<1] = tree[rt<<1|1] = lazy[rt];
        lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
        lazy[rt] = 0;
    }
}

void query(int L, int R, int l, int r, int rt) {
    if (L <= l && r <= R && (~tree[rt])) { 
        if(tree[rt]) que[++tail] = tree[rt];
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) query(L,R,l,mid,rt<<1);
    if(mid<R) query(L,R,mid+1,r,rt<<1|1);
    pushup(rt);
}

void update(int L, int R, int l, int r, int rt, int k) {
    if (L <= l && r<= R) {
        tree[rt] = lazy[rt] = k;
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid) update(L,R,l,mid,rt<<1,k);
    if(mid<R) update(L,R,mid+1,r,rt<<1|1,k);
    pushup(rt);
}


signed main() {
    cin>>n;
    string cmd;
    for (int i = 1; i <= n; i++) {
        cin>>cmd;
        if (cmd[0] == 'A') {
            cin>>x[i]>>y[i];
            tail = 0;
            query(x[i], y[i], 1, N, 1);
            cnt = 0;
            for (int j = 1; j <= tail; j++)
                if (!vis[que[j]]) { 
                    int s = x[que[j]], t = y[que[j]];
                    update(s,t,1,N,1,0);
                    vis[que[j]] = true;
                    cnt++;
                }
            update(x[i],y[i],1,N,1,i);
            cout<<cnt<<endl;
            sum = sum - cnt + 1;
        }
        else
            cout<<sum<<endl;
    }
    return 0;
}

orz stl解法

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, N = 1e5;

struct node{
    int l,r;
    bool operator < (const node &x) const{
        return r<x.l;
    }
};

int n;
set<node> s;

int main(){
    cin>>n;
    while(n--){
        string op;
        cin>>op;
        if(op=="A"){
           	int l,r,ans=0;
           	cin>>l>>r;
            node x=(node){l,r};
            set<node>::iterator i=s.find(x);
            while(i!=s.end()){
                ans++;
                s.erase(i);
                i=s.find(x);
            }
            s.insert(x);
            cout<<ans<<endl;
        }
        else cout<<s.size()<<endl;
    }
    return 0;
}