题目链接

题意

  • 有区间$[1…N](1\leq N \leq 1e8)$, $Q(1\leq Q \leq 1e5)$次操作,初始全部为false每次操作为:
    1, 区间$[l,r]$设置为true
    2, 询问区间$[l,r]$还有多少个false

算法

  • 离散 & 线段树

思路

  • 我们把询问离散化,建立线段树,节点存区间内还剩多少个false,记为$sum$
  • 令$f(l,r)=fp_r-fp_l+1$表示真实区间的大小,$fp$表示离散化时p对应的真实数
  • 更新的时候如果某个节点的两个子节点均被标记过(全部被染色),那么这个节点也肯定全被染色,也就是说不会存在左节点被染了,右节点也被染了,中间还有些点没染,节点的剩余数为总数量减去已被染色的数量$sum=f(l,r)-(f(l,mid)-sum_{left})-(f(mid+1,r)-sum_{right})$
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
typedef long long LL;
typedef unsigned long long ULL;
static const int mod = 100000007;
static const int maxN = 3e5 + 10;
typedef std::pair<int, int>PII;
bool lazy[maxN << 2];
int sum[maxN << 2];
std::map<int, int>hsMap;
int ql[maxN], qr[maxN], qt[maxN]; //l,r,type
int fp[maxN];
inline int compute(int l, int r) {
return fp[r] - fp[l] + 1;
}
inline void build(int l, int r, int v) {
lazy[v] = false;
sum[v] = compute(l, r);
if (l >= r) {
return;
}
int mid = l + r >> 1;
build(l, mid, v << 1);
build(mid + 1, r, v << 1 | 1);
}
inline void pushUp(int l, int r, int v) {
lazy[v] = lazy[v << 1] && lazy[v << 1 | 1];
if (lazy[v << 1] && lazy[v << 1 | 1]) {
sum[v] = 0;
return;
}
int mid = l + r >> 1;
sum[v] = compute(l, r) - (compute(l, mid) - sum[v << 1]) - (compute(mid + 1, r) - sum[v << 1 | 1]);
}
inline void update(int l, int r, int x, int y, int v) {
if (l >= x && r <= y) {
lazy[v] = true;
sum[v] = 0;
return;
}
if (lazy[v]) return;
int mid = l + r >> 1;
if (x <= mid) update(l, mid, x, y, v << 1);
if (mid < y) update(mid + 1, r, x, y, v << 1 | 1);
pushUp(l, r, v);
}
inline int query(int l, int r, int x, int y, int v) {
if (l >= x && r <= y) {
return sum[v];
}
if (lazy[v]) return 0;
int mid = l + r >> 1;
int result = 0;
if (x <= mid) result = query(l, mid, x, y, v << 1);
if (mid < y) result += query(mid + 1, r, x, y, v << 1 | 1);
return result;
}
int main() {
int n, q;
hsMap.clear();
scanf("%d%d", &n, &q);
for (int i = 0; i < q; ++i) {
scanf("%d%d%d", qt + i, ql + i, qr + i);
if (ql[i] - 1) hsMap[ql[i] - 1] = 1;
hsMap[ql[i]] = 1;
hsMap[ql[i] + 1] = 1;
if (qr[i] - 1) hsMap[qr[i] - 1] = 1;
hsMap[qr[i]] = 1;
hsMap[qr[i] + 1] = 1;
}
int pos = 0;
for (std::map<int, int>::iterator iter = hsMap.begin(); iter != hsMap.end(); ++iter) {
iter->second = ++pos;
fp[pos] = iter->first;
}
build(1, pos, 1);
for (int i = 0; i < q; ++i) {
if (1 == qt[i]) update(1, pos, hsMap[ql[i]], hsMap[qr[i]], 1);
if (2 == qt[i]) printf("%d\n", query(1, pos, hsMap[ql[i]], hsMap[qr[i]], 1));
}
return 0;
}

留言

2016-04-24