51nod 小朋友的笑话

链接

分析:

  每次操作把以前没有出现这个数的设为1,有这个数的设为0。首先将当前区间设为1,考虑有set维护这个颜色出现的区间,然后把所有与当前区间相交的拿出来,修改为0。

  复杂度?每次操作的线段只会加入到一次set中,从set中取出一次,只会修改一次,然后就合并成大的了,每次操作也只会加入一条线段。

代码:

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<bitset>
#define pa pair<int,int>
using namespace std;
typedef long long LL;

inline int read() {
    int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
}

const int N = 100005;
set< pa > s[N];
int n;

struct SegmentTree{
    int sum[N << 2], tag[N << 2], n;
    SegmentTree() { memset(tag, -1, sizeof(tag)); }
    void pushdown(int rt,int len) {
        tag[rt << 1] = tag[rt], tag[rt << 1 | 1] = tag[rt];
        sum[rt << 1] = tag[rt] * (len - len / 2);
        sum[rt << 1 | 1] = tag[rt] * (len / 2);
        tag[rt] = -1;
    }
    void update(int l,int r,int rt,int L,int R,int v) {
        if (L > R) return ;
        if (L <= l && r <= R) { tag[rt] = v, sum[rt] = v * (r - l + 1); return ; }
        if (~tag[rt]) pushdown(rt, r - l + 1);
        int mid = (l + r) >> 1;
        if (L <= mid) update(l, mid, rt << 1, L, R, v);
        if (R > mid) update(mid + 1, r, rt << 1 | 1, L, R, v);
        sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    }
    int query(int l,int r,int rt,int L,int R) {
        if (L <= l && r <= R) return sum[rt];
        if (~tag[rt]) pushdown(rt, r - l + 1);
        int mid = (l + r) >> 1, res = 0;
        if (L <= mid) res = query(l, mid, rt << 1, L, R);
        if (R > mid) res += query(mid + 1, r, rt << 1 | 1, L, R);
        return res;
    }
}T;
void Insert() {
    int x = read(), y = read(), k = read(), l = max(1, x - k), r = min(n, x + k), nowl = l, nowr = r;
    if (s[y].empty()) {
        T.update(1, n, 1, l, r, 1);
        s[y].insert(pa(l, r)); return ; 
    }
    set< pa > :: iterator it = s[y].lower_bound(pa(l, 0));
    set< pa > :: iterator pre = it;
    
    if (it != s[y].begin()) {
        pre --;
        if (pre->second >= l) it = pre;
    }
    if (it == s[y].end() || (it->first) > r) {
        T.update(1, n, 1, l, r, 1);
        s[y].insert(pa(l, r)); return ;
    }
    nowl = min(nowl, it->first);
    T.update(1, n, 1, l, r, 1);
    while (it != s[y].end() && (it->first) <= r) {
        T.update(1, n, 1, max(l, it->first), min(r, it->second), 0);
        nowr = max(nowr, it->second);
        pre = it; it ++; s[y].erase(pre);
    }
    s[y].insert(pa(nowl, nowr));    
}
void query() {
    int l = read(), r = read();
    printf("%d
", T.query(1, n, 1, l, r));
}
int main() {
    n = read();int m = read();
    for (int i = 1; i <= m; ++i) {
        if (read() == 1) Insert();
        else query();        
    }
    return 0;
}
原文地址:https://www.cnblogs.com/mjtcn/p/10591716.html