• 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 }
  • 相关阅读:
    为什么下水井盖是圆的
    静心尽力
    菜鸟的一年
    [转]Libev教程
    流媒体:V4L2视频获取
    [转]Libev源码分析 -- 整体设计
    c#操作xml增删改查
    dwz简单配置与操作
    jsonp 跨域访问
    操作cookie.判断浏览器系统版本,判断safir浏览器存储数据
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4807954.html
Copyright © 2020-2023  润新知