pku 3277 离散化建树

  离散化真的是一个很神奇的东西,其实就是另建一个hash表映射所有的坐标,在对付总体范围较大或者重复很多的情况时有神奇的效果,前两场比赛时碰到了两道离散化的题目,出现的几率还是很高的,觉得有必要学习一下,但是昨天下午。。。(神啊,原谅我吧!)。

  用线段树处理举行并的面积暂时还不会,二维的线段树怎么处理呢?(我猜应该先降低维度)。这道题是求一维的情况,还不算是经典的线段树,只能算离散化的入门题目吧!

  线段树很是博大精深啊,有两种经典的建树模型,连续型和分段型,这里采用的是第一种,特别注意的是处理时小心空区,什么是空区呢,就是树中的某一条线段没有值,这里的没有值容易和零值搞混,零值需要继续递归求解,而空区要直接跳出了,所以,预处理和赋值时要区别开着两种情况。

pku 3277代码如下:

 

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
1 #include < iostream >
2 #include < algorithm >
3   using namespace std;
4
5   #define MAX 80010
6 struct point{
7 int a,b,h;
8 } p[MAX];
9 struct Node{
10 int l,r,h;
11 } Tree[ 6 * MAX];
12 int hash[MAX],index;
13 __int64 ans;
14 bool cmp(point a,point b)
15 {
16 return a.h < b.h;
17 }
18 void build( int l, int r, int k)
19 {
20 Tree[k].l = l;
21 Tree[k].r = r;
22 Tree[k].h = 0 ;
23 if (l + 1 == r) return ;
24 int mid = (l + r) / 2 ;
25 build(l,mid, 2 * k);
26 build(mid,r, 2 * k + 1 );
27 }
28 int find( int x)
29 {
30 int l = 0 ,r = index - 1 ;
31 while (l <= r){
32 int mid = (l + r) / 2 ;
33 if (hash[mid] == x) return mid;
34 else {
35 if (hash[mid] > x) r = mid - 1 ;
36 else l = mid + 1 ;
37 }
38 }
39 }
40 void update( int l, int r, int h, int k)
41 {
42 if (Tree[k].l == l && Tree[k].r == r) {Tree[k].h = h; return ; }
43 if (Tree[k].h >= 0 ){
44 Tree[ 2 * k].h = Tree[k].h; Tree[ 2 * k + 1 ].h = Tree[k].h; Tree[k].h = - 1 ;
45 }
46 int mid = (Tree[k].l + Tree[k].r) / 2 ;
47 if (l >= mid) update(l,r,h, 2 * k + 1 );
48 else if (r <= mid) update(l,r,h, 2 * k);
49 else {update(l,mid,h, 2 * k); update(mid,r,h, 2 * k + 1 ); }
50
51 }
52 void solve( int k)
53 {
54 if (Tree[k].h > 0 ) {ans += (hash[Tree[k].r] - hash[Tree[k].l]) * __int64(Tree[k].h); return ;}
55 else if (Tree[k].h == - 1 ){
56 solve( 2 * k);
57 solve( 2 * k + 1 );
58 }
59 }
60 int main()
61 {
62 int n,nn,i;
63 while (scanf ( " %d " , & n) != EOF){
64 for (i = 0 ,index = 0 ; i < n; i ++ ){
65 scanf ( " %d%d%d " , & p[i].a, & p[i].b, & p[i].h);
66 hash[index ++ ] = p[i].a; hash[index ++ ] = p[i].b;
67 }
68 sort(hash,hash + index); sort(p,p + n,cmp);
69 for (i = 1 ,nn = index,index = 1 ; i < nn; i ++ )
70 if (hash[i] != hash[i - 1 ]) hash[index ++ ] = hash[i];
71 build( 0 ,index - 1 , 1 );
72 for (i = 0 ; i < n; i ++ )
73 update(find(p[i].a),find(p[i].b),p[i].h, 1 );
74 ans = 0 ; solve( 1 );
75 printf ( " %I64d\n " ,ans);
76 }
77 return 0 ;
78 }

 

转载于:https://www.cnblogs.com/looker_acm/archive/2010/08/13/1798874.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值