spoj 2713 线段树

给定一个序列,有两种操作:对一个区间内的数字开方和求区间内所有数字的和。注意到一个即使很大的数经过没几次开方操作以后就会变成1,而1开方还是1。所以可以用线段树来维护,对于那些全部都是1的区间(即区间和等于区间长度)我们不用更新,剩下的就是区间求和了。

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cmath>
  5 using namespace std;
  6 
  7 typedef long long ll;
  8 const int N = 100001;
  9 ll a[N];
 10 int n, m;
 11 
 12 struct Node 
 13 {
 14     int l, r;
 15     ll sum;
 16 } node[N << 2];
 17 
 18 void pushup( int i )
 19 {
 20     node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;
 21 }
 22 
 23 void build( int i, int l, int r )
 24 {
 25     node[i].l = l, node[i].r = r;
 26     if ( l == r )
 27     {
 28         node[i].sum = a[l];
 29         return ;
 30     }
 31     int mid = ( l + r ) >> 1;
 32     build( i << 1, l, mid );
 33     build( i << 1 | 1, mid + 1, r );
 34     pushup(i);
 35 }
 36 
 37 void update( int i, int l, int r )
 38 {
 39     int len = node[i].r - node[i].l + 1;
 40     if ( node[i].sum == len ) return ;
 41     int mid = ( node[i].l + node[i].r ) >> 1;
 42     if ( node[i].l == l && node[i].r == r )
 43     {
 44         if ( len == 1 )
 45         {
 46             node[i].sum = sqrt( node[i].sum * 1.0 );
 47         }
 48         else
 49         {
 50             update( i << 1, l, mid );
 51             update( i << 1 | 1, mid + 1, r );
 52             pushup(i);
 53         }
 54         return ;
 55     }
 56     if ( r <= mid )
 57     {
 58         update( i << 1, l, r );
 59     }
 60     else if ( l > mid )
 61     {
 62         update( i << 1 | 1, l, r );
 63     }
 64     else
 65     {
 66         update( i << 1, l, mid );
 67         update( i << 1 | 1, mid + 1, r );
 68     }
 69     pushup(i);
 70 }
 71 
 72 ll query( int i, int l, int r )
 73 {
 74     if ( node[i].l == l && node[i].r == r )
 75     {
 76         return node[i].sum;
 77     }
 78     int mid = ( node[i].l + node[i].r ) >> 1;
 79     if ( r <= mid )
 80     {
 81         return query( i << 1, l, r );
 82     }
 83     else if ( l > mid )
 84     {
 85         return query( i << 1 | 1, l, r );
 86     }
 87     else
 88     {
 89         return query( i << 1, l, mid ) + query( i << 1 | 1, mid + 1, r );
 90     }
 91 }
 92 
 93 int main ()
 94 {
 95     int _case = 1;
 96     while ( scanf("%d", &n) != EOF )
 97     {
 98         printf("Case #%d:
", _case++);
 99         for ( int i = 1; i <= n; i++ )
100         {
101             scanf("%lld", &a[i]);
102         }
103         build( 1, 1, n );
104         scanf("%d", &m);
105         while ( m-- )
106         {
107             int op, x, y;
108             scanf("%d%d%d", &op, &x, &y);
109             if ( x > y ) swap( x, y );
110             if ( op == 0 )
111             {
112                 update( 1, x, y );
113             }
114             else
115             {
116                 ll ans = query( 1, x, y );
117                 printf("%lld
", ans);
118             }
119         }
120         putchar('
');
121     }
122     return 0;
123 }
原文地址:https://www.cnblogs.com/huoxiayu/p/4807954.html