线段树模型

源自:http://www.cnblogs.com/jiaohuang/archive/2010/09/23/1833440.html

1投影线段总的长度

//x轴上有若干条线段,求线段覆盖的总长度。

 

代码
复制代码
   
1 #include < cstdio > 2 #include < cstring > 3 4   using namespace std; 5 6   #define maxn 2001 7 8 typedef struct { 9 int cover; 10 }TreeNode; 11 TreeNode tree[maxn]; 12 13   void Insert( int p, int l, int r, int a, int b){ 14 int m; 15 if (tree[p].cover == 0 ) 16 { 17 m = (l + r) / 2 ; 18 if (a == l && b == r) 19 { 20 tree[p].cover = 1 ; 21 } 22 else if (b <= m) 23 Insert(p * 2 , l , m , a , b); 24 else if (a >= m) 25 Insert(p * 2 + 1 , m , r , a, b); 26 else 27 { 28 Insert(p * 2 , l , m , a , m); 29 Insert(p * 2 + 1 , m , r , m , b); 30 } 31 } 32 } 33 34   int Count( int p , int l, int r){ 35 if (tree[p].cover == 1 ) 36 return r - l; 37 else if (r - l <= 1 ) return 0 ; 38 else return Count(p * 2 , l ,(l + r) / 2 ) + Count(p * 2 + 1 , (l + r) / 2 , r); 39 } 40 41 42   int main(){ 43 int nl, nr; 44 memset(tree, 0 , sizeof (tree)); 45 while ( 1 ) 46 { 47 scanf( " %d %d " , & nl, & nr); 48 if (nl == 0 && nr == 0 ) break ; 49 Insert( 1 , 1 , 1000 , nl , nr); 50 } 51 printf( " %d\n " , Count( 1 , 1 , 1000 ) ); 52 return 0 ; 53 } 54  
复制代码

 

 

2投影线段的颜色种类

//x轴上有若干条不同线段,将它们依次染上不同的颜色,问最后能看到多少种不同的颜色?//(后染的颜色会覆盖原先的颜色)

//我们可以这样规定:x轴初始是颜色0,第一条线段染颜色1,第二条线段染颜色2,以此//类推.

代码
复制代码
    
1 #include < cstdio > 2 #include < cstring > 3 4   using namespace std; 5 6   #define maxn 2001 7 8 typedef struct { 9 int cover; 10 }TreeNode; 11 TreeNode tree[maxn]; 12 int flag[maxn]; 13 14 void Insert( int p, int l, int r, int a, int b, int color){ 15 int m; 16 if (tree[p].cover != color) 17 { 18 m = (l + r) / 2 ; 19 if (a == l && b == r) 20 tree[p].cover = color; 21 else 22 { 23 if (tree[p].cover >= 0 ) 24 { 25 tree[p * 2 ].cover = tree[p].cover; 26 tree[p * 2 + 1 ].cover = tree[p].cover; 27 tree[p].cover = - 1 ; 28 } 29 if (b <= m) 30 Insert(p * 2 , l , m , a , b , color); 31 else if (a >= m) 32 Insert(p * 2 + 1 , m , r , a, b , color); 33 else 34 { 35 Insert(p * 2 , l , m , a , m , color); 36 Insert(p * 2 + 1 , m , r , m , b , color); 37 } 38 } 39 } // if 40 } 41 42 void Count( int p , int l, int r){ 43 if (tree[p].cover >= 0 ) 44 { 45 flag[tree[p].cover ] = 1 ; 46 return ; 47 } 48 else if (r - l == 1 ) return ; 49 else 50 { 51 Count(p * 2 , l ,(l + r) / 2 ) ; 52 Count(p * 2 + 1 , (l + r) / 2 , r); 53 } 54 } 55 56 57 int main(){ 58 int nl, nr , ncolor; 59 int ans = 0 ; 60 memset(tree, 0 , sizeof (tree)); 61 memset(flag , 0 , sizeof (flag)); 62 while ( 1 ) 63 { 64 scanf( " %d %d " , & nl, & nr); 65 if (nl == 0 && nr == 0 ) break ; 66 scanf( " %d " , & ncolor); 67 Insert( 1 , 1 , 1000 , nl , nr , ncolor); 68 } 69 Count( 1 , 1 , 1000 ); 70 for ( int i = 0 ; i < maxn ; i ++ )ans += flag[i]; 71 printf( " %d\n " , ans - 1 ); // 0 72 return 0 ; 73 } 74
复制代码

 

3 x轴被不同颜色分成多少段

//线段的颜色可以相同。连续的相同颜色被视作一段

 

代码
复制代码
   
1 #include < cstdio > 2 #include < cstring > 3 4 using namespace std; 5 6 #define maxn 2001 7 8 typedef struct { 9 int cover; 10 }TreeNode; 11 TreeNode tree[maxn]; 12 13 void Insert( int p, int l, int r, int a, int b, int color){ 14 int m; 15 if (tree[p].cover != color) 16 { 17 m = (l + r) / 2 ; 18 if (a == l && b == r) 19 tree[p].cover = color; 20 else 21 { 22 if (tree[p].cover >= 0 ) 23 { 24 tree[p * 2 ].cover = tree[p].cover; 25 tree[p * 2 + 1 ].cover = tree[p].cover; 26 tree[p].cover = - 1 ; 27 } 28 if (b <= m) 29 Insert(p * 2 , l , m , a , b , color); 30 else if (a >= m) 31 Insert(p * 2 + 1 , m , r , a, b , color); 32 else 33 { 34 Insert(p * 2 , l , m , a , m , color); 35 Insert(p * 2 + 1 , m , r , m , b , color); 36 } 37 } 38 } // if 39 } 40 41 int Count( int p , int l, int r , int & lc , int & rc){ 42 int result , tl ,tr ; 43 if (tree[p].cover >= 0 ) 44 { 45 lc = tree[p].cover; 46 rc = tree[p].cover; 47 if (tree[p].cover > 0 ) return 1 ; 48 else return 0 ; 49 } 50 else if (r - l > 1 ) 51 { 52 result = Count(p * 2 , l , (l + r) / 2 , lc , tl) + Count(p * 2 + 1 , (l + r) / 2 ,r ,tr ,rc); 53 if (tl == tr && tl > 0 ) // the left and right sides are of the same color 54 result -= 1 ; 55 return result; 56 } 57 } 58 59 60 int main(){ 61 int nl , nr , ncolor; 62 int lc, rc; 63 int ans = 0 ; 64 memset(tree, 0 , sizeof (tree)); 65 while ( 1 ) 66 { 67 scanf( " %d %d " , & nl, & nr); 68 if (nl == 0 && nr == 0 ) break ; 69 scanf( " %d " , & ncolor); 70 Insert( 1 , 1 , 1000 , nl , nr , ncolor); 71 } 72 printf( " %d\n " , Count( 1 , 1 , 1000 , rc , lc)); // 0 73 return 0 ; 74 } 75
复制代码

 

 

4 x轴上有若干条不同线段,问某个单位区间[x,x+1]上重叠了多少条线段?

 

代码
复制代码
   
1 #include < cstdio > 2 #include < cstring > 3 4 using namespace std; 5 6 #define maxn 2001 7 8 typedef struct { 9 int cover , count; 10 }TreeNode; 11 TreeNode tree[maxn]; 12 13 void Insert( int p, int l, int r, int a, int b){ 14 int m; 15 m = (l + r) / 2 ; 16 if (a == l && b == r) 17 tree[p].count += 1 ; 18 else 19 { 20 if (b <= m) 21 Insert(p * 2 , l , m , a , b ); 22 else if (a >= m) 23 Insert(p * 2 + 1 , m , r , a, b ); 24 else 25 { 26 Insert(p * 2 , l , m , a , m ); 27 Insert(p * 2 + 1 , m , r , m , b ); 28 } 29 } 30 } 31 32 int Count( int p , int l, int r , int a , int b){ 33 int result , m; 34 result = 0 ; 35 while ( 1 ) 36 { 37 m = (l + r) / 2 ; 38 result = result + tree[p].count; 39 if (a == l && b == r) break ; 40 if (b <= m)r = m , p = 2 * p; 41 else if ( a >= m)l = m , p = 2 * p + 1 ; 42 } 43 return result; 44 } 45 46 47 int main(){ 48 int nl, nr , ncolor; 49 int lc, rc; 50 int ans = 0 ; 51 memset(tree, 0 , sizeof (tree)); 52 while ( 1 ) 53 { 54 scanf( " %d %d " , & nl, & nr); 55 if (nl == 0 && nr == 0 ) break ; 56 Insert( 1 , 1 , 1000 , nl , nr ); 57 } 58 printf( " %d\n " , Count( 1 , 1 , 1000 , 9 , 10 )); // 0 59 return 0 ; 60 } 61
复制代码

 

 

5树状数组

//求[a , b]区间内的和 , 可以动态改变数组的值

代码
复制代码
   
1 #include < cstdio > 2 #include < cstring > 3 4 5 #define MAXN 10000+1 // the max number 6 int num[MAXN]; // the first number must be num[1]!! 7 8 int Lowbit( int x) // (x --> 2^k) 9 { 10 return x & (x ^ (x - 1 )); 11 } 12 13 int Sum( int x) // x>=0 14 { 15 int result; 16 result = 0 ; 17 while (x > 0 ) 18 { 19 result = result + num[x]; 20 x = x - Lowbit( x ); 21 } 22 return result; 23 } 24 25 void Modify( int p , int delta){ 26 while ( p <= MAXN) 27 { 28 num[p] = num[p] + delta; 29 p = p + Lowbit(p); 30 } 31 } 32 33 int main(){ 34 int nt , nplace; 35 memset(num , 0 , sizeof (num)); 36 while ( 1 ) 37 { 38 scanf( " %d %d " , & nplace, & nt); 39 if (nplace == 0 && nt == 0 ) break ; 40 Modify(nplace , nt); 41 } 42 43 return 0 ; 44 } 45
复制代码

 


 

 

 

6二维树状数组

代码
复制代码
    
1 #include < cstdio > 2 #include < cstring > 3 4 5 #define MAXN 1000+1 // the max number 6 int num[MAXN][MAXN]; // the first number must be num[1][1]!! 7 8 int Lowbit( int x) // (x --> 2^k) 9 { 10 return x & (x ^ (x - 1 )); 11 } 12 13 int Sum( int x , int y) // x>=0 14 { 15 int result , t; 16 result = 0 ; 17 while (x > 0 ) 18 { 19 t = y; 20 while (t > 0 ) 21 { 22 result = result + num[x][t]; 23 t = t - Lowbit(t); 24 } 25 x = x - Lowbit(x); 26 } 27 return result; 28 } 29 30 void Modify( int x , int y , int delta){ 31 int t; 32 while ( x < MAXN) 33 { 34 t = y; 35 while (t < MAXN) 36 { 37 num[x][t] = num[x][t] + delta; 38 t = t + Lowbit(t); 39 } 40 x = x + Lowbit( x ); 41 } 42 } 43 44 int main(){ 45 int nt , nx , ny; 46 memset(num , 0 , sizeof (num)); 47 while ( 1 ) 48 { 49 scanf( " %d %d %d " , & nx , & ny, & nt); 50 if (nx == 0 && ny == 0 ) break ; 51 Modify(nx , ny , nt); 52 } 53 printf( " %d \n " , Sum( 100 , 100 )); 54 return 0 ; 55 } 56
复制代码

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值