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\n", 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; }