码迷,mamicode.com
首页 > 其他好文 > 详细

hicocoder1079离散化+线段树

时间:2015-02-22 15:44:39      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:

题目链接: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 }

 

hicocoder1079离散化+线段树

标签:

原文地址:http://www.cnblogs.com/pczhou/p/4297511.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!