Description
Input
题目大意:给n个区间,每个区间上一种颜色(会覆盖掉之前的),问最终还有多少种颜色在上面。
思路:线段树水题,不多说了。先离散化,详细看代码,可能方法比较奇葩……最后还有一点要注意的是区间[l, r]是指第l条线段到第r条线段,而不是第l个点到第r个点。
代码(63MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 const int MAXN = 10010; 8 9 struct Node { 10 int x, id; 11 bool operator < (const Node &rhs) const { 12 return x < rhs.x; 13 } 14 }; 15 16 int tree[MAXN * 4]; 17 Node a[MAXN * 2]; 18 int l[MAXN], r[MAXN]; 19 int n, cnt, m; 20 21 void pushdown(int x) { 22 if(!tree[x]) return ; 23 int ll = x << 1, rr = ll ^ 1; 24 tree[ll] = tree[rr] = tree[x]; 25 tree[x] = 0; 26 } 27 28 void update(int x, int left, int right, int L, int R, int key) { 29 if(L <= left && right <= R) { 30 tree[x] = key; 31 } 32 else { 33 pushdown(x); 34 int ll = x << 1, rr = ll ^ 1; 35 int mid = (left + right) >> 1; 36 if(L < mid) update(ll, left, mid, L, R, key); 37 if(mid < R) update(rr, mid, right, L, R, key); 38 } 39 } 40 41 bool vis[MAXN]; 42 43 int query(int x, int left, int right) { 44 int ret = 0; 45 if(tree[x]) { 46 if(!vis[tree[x]]) { 47 vis[tree[x]] = true; 48 ret = 1; 49 } 50 } 51 else { 52 if(right - left == 1) return 0; 53 int ll = x << 1, rr = ll ^ 1; 54 int mid = (left + right) >> 1; 55 ret += query(ll, left, mid); 56 ret += query(rr, mid, right); 57 } 58 return ret; 59 } 60 61 int main() { 62 int T; 63 scanf("%d", &T); 64 while(T--) { 65 scanf("%d", &n); 66 cnt = 0; 67 for(int i = 0; i < n; ++i) { 68 scanf("%d%d", &l[i], &r[i]); 69 a[cnt].x = l[i]; a[cnt++].id = i; 70 a[cnt].x = r[i] + 1; a[cnt++].id = i + MAXN; 71 } 72 sort(a, a + cnt); 73 m = 1; 74 for(int i = 0; i < cnt; ++i) { 75 if(i > 0 && a[i - 1].x != a[i].x) ++m; 76 if(a[i].id < MAXN) l[a[i].id] = m; 77 else r[a[i].id - MAXN] = m; 78 } 79 memset(tree, 0, sizeof(tree)); 80 for(int i = 0; i < n; ++i) 81 update(1, 1, m, l[i], r[i], i + 1); 82 memset(vis, 0, sizeof(vis)); 83 int ans = query(1, 1, m); 84 printf("%d\n", ans); 85 } 86 }