题目链接:http://hihocoder.com/problemset/problem/1079
题目大意:
有一条数轴,先后对数轴上的一些区间着上不同的颜色,后着色的区间若跟先着色的区间有重合,则重合部分颜色将被后着色的区间颜色覆盖,求在一系列的区间着色操作之后,最终数轴上的颜色有几种。区间数目n<=10^5, 区间长度最大值L<=10^9.
这道题目乍看上去就是一道简单的线段树区间更新区间查询的问题,但仔细一看发现,区间长度最大值L可能达到10^9,若按照普通的线段树来做,内存根本开不下。
这时候我们注意到:假设现在有两个区间要着色,并求最后颜色有几种,我们对区间[0, 100000000]和[2, 1000000001]着色其实与对区间[0, 2]和[1, 3]着色对我们的答案并没有任何影响,因为将区间[0, 100000000]和[2, 1000000001]改为[0, 2]和[1, 3]并没有改变区间端点之间的相对大小。
所以,离散化要做的就是,先将所有的2*n个区间端点记录下来,并将每个端点值映射到另外一个值上,只要不改变其相对大小关系,若我们的映射值从0开始逐1增加,那么最后得到的所有映射值的最大值不会超过2*n个。这样映射以后,再用线段树来做,就不存在内存开不下的问题了。
另外需要注意的是:这里的线段树区间是连续的,与区间离散的线段树最明显的不同是,前者左右儿子表示的区间为[l, m]、[m+1, r]这种形式而后者表示的区间为[l, m]、 [m, r]这种形式,前者的叶子节点表示的区间为[i, i]这种形式而后者的叶节点表示的区间为[i, i+1]这种形式。
我的代码:
1 #include <iostream> 2 #include <set> 3 #include <map> 4 5 using namespace std; 6 7 #define MAXN 2*100005 8 9 int ll[MAXN/2], rr[MAXN/2]; 10 set<int> st; 11 map<int, int> mp; 12 13 struct segNode 14 { 15 int left, right, id; 16 bool lazy; 17 }; 18 19 struct segTree 20 { 21 segNode t[4*MAXN]; 22 void build(int i, int l, int r) 23 { 24 t[i].left = l; 25 t[i].right = r; 26 t[i].lazy = false; 27 if(l+1<r) 28 { 29 int m = (l+r)/2; 30 build(2*i, l, m); 31 build(2*i+1, m, r); 32 } 33 } 34 void pushdown(int i) 35 { 36 t[i].lazy = false; 37 t[2*i].id = t[i].id; 38 t[2*i+1].id = t[i].id; 39 t[2*i].lazy = true; 40 t[2*i+1].lazy = true; 41 } 42 void update(int i, int l, int r, int v) 43 { 44 if(t[i].left+1<t[i].right&&t[i].lazy) pushdown(i); 45 if(t[i].left==l&&t[i].right==r) 46 { 47 t[i].id = v; 48 t[i].lazy = true; 49 } 50 else 51 { 52 int m = (t[i].left+t[i].right)/2; 53 if(r<=m) update(2*i, l, r, v); 54 else if(l>=m) update(2*i+1, l, r, v); 55 else 56 { 57 update(2*i, l, m, v); 58 update(2*i+1, m, r, v); 59 } 60 } 61 } 62 void query(int i) 63 { 64 if(t[i].lazy) st.insert(t[i].id); 65 else if(t[i].left+1<t[i].right) 66 { 67 query(2*i); 68 query(2*i+1); 69 } 70 } 71 }tree; 72 73 int main() 74 { 75 int n, l; 76 while(cin>>n>>l) 77 { 78 st.clear(); 79 mp.clear(); 80 for(int i=0; i<n; ++i) 81 { 82 cin>>ll[i]>>rr[i]; 83 st.insert(ll[i]); 84 st.insert(rr[i]); 85 } 86 int cnt = 0; 87 for(set<int>::iterator it=st.begin(); it!=st.end(); it++) mp[*it] = cnt++; 88 st.clear(); 89 tree.build(1, 0, cnt-1); 90 for(int i=0; i<n; ++i) tree.update(1, mp[ll[i]], mp[rr[i]], i); 91 tree.query(1); 92 cout<<st.size()<<endl; 93 } 94 return 0; 95 }