zoukankan      html  css  js  c++  java
  • hdu 3074 线段树 OR 树状数组

    比较基础的线段树,1A。

    线段树:

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 using namespace std;
      5 
      6 typedef long long ll;
      7 const int N = 50001;
      8 const int MOD = 1000000007;
      9 int a[N];
     10 
     11 struct Node
     12 {
     13     int l, r, s;
     14 } node[N << 2];
     15 
     16 void pushup( int i )
     17 {
     18     node[i].s = ( ll ) node[i << 1].s * node[i << 1 | 1].s % MOD;
     19 }
     20 
     21 void build( int i, int l, int r )
     22 {
     23     node[i].l = l, node[i].r = r;
     24     if ( l == r )
     25     {
     26         node[i].s = a[l];
     27         return ;
     28     }
     29     int mid = ( l + r ) >> 1;
     30     build( i << 1, l, mid );
     31     build( i << 1 | 1, mid + 1, r );
     32     pushup(i);
     33 }
     34 
     35 void update( int i, int pos, int val )
     36 {
     37     if ( node[i].l == pos && node[i].r == pos )
     38     {
     39         node[i].s = val;
     40         return ;
     41     }
     42     int mid = ( node[i].l + node[i].r ) >> 1;
     43     if ( pos <= mid )
     44     {
     45         update( i << 1, pos, val );
     46     }
     47     else
     48     {
     49         update( i << 1 | 1, pos, val );
     50     }
     51     pushup(i);
     52 }
     53 
     54 int query( int i, int l, int r )
     55 {
     56     if ( node[i].l == l && node[i].r == r ) return node[i].s;
     57     int mid = ( node[i].l + node[i].r ) >> 1;
     58     if ( r <= mid )
     59     {
     60         return query( i << 1, l, r );
     61     }
     62     else if ( l > mid )
     63     {
     64         return query( i << 1 | 1, l, r );
     65     }
     66     else
     67     {
     68         return ( ll ) query( i << 1, l, mid ) * query( i << 1 | 1, mid + 1, r ) % MOD;
     69     }
     70 }
     71 
     72 int main ()
     73 {
     74     int t;
     75     scanf("%d", &t);
     76     while ( t-- )
     77     {
     78         int n, m;
     79         scanf("%d", &n);
     80         for ( int i = 1; i <= n; i++ )
     81         {
     82             scanf("%d", a + i);
     83         }
     84         build( 1, 1, n );
     85         scanf("%d", &m);
     86         while ( m-- )
     87         {
     88             int op, a, b;
     89             scanf("%d%d%d", &op, &a, &b );
     90             if ( op == 0 )
     91             {
     92                 printf("%d
    ", query( 1, a, b ));
     93             }
     94             else
     95             {
     96                 update( 1, a, b );
     97             }
     98         }
     99     }
    100     return 0;
    101 }

    当然,对于这种单点修改和查询区间“前缀和”的问题,我们自然也可以用树状数组来做,不过要用到乘法逆元。

    对于这道题来说,树状数组反而难写,并且时间上也没有什么优势。

    不过这是一种思想,将“加法”扩展到了“乘法”。

    也可以考虑用log把乘法变成加法,不过可能会有精度问题。

    树状数组:

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 
     6 typedef long long ll;
     7 const int N = 50001;
     8 const int MOD = 1000000007;
     9 int a[N];
    10 int c[N];
    11 
    12 void extgcd( int a, int mod, int &x, int &y )
    13 {
    14     if ( !mod )
    15     {
    16         x = 1, y = 0;
    17     }
    18     else
    19     {
    20         extgcd( mod, a % mod, y, x );
    21         y -= x * ( a / mod );
    22     }
    23 }
    24 
    25 int lb( int i )
    26 {
    27     return i & -i;
    28 }
    29 
    30 void update( int i, int x )
    31 {
    32     while ( i < N )
    33     {
    34         c[i] = ( ll ) c[i] * x % MOD;
    35         i += lb(i);
    36     }
    37 }
    38 
    39 int get( int i )
    40 {
    41     int ans = 1;
    42     while ( i )
    43     {
    44         ans = ( ll ) ans * c[i] % MOD;
    45         i -= lb(i);
    46     }
    47     return ans;
    48 }
    49 
    50 int main ()
    51 {
    52     int t;
    53     scanf("%d", &t);
    54     while ( t-- )
    55     {
    56         int n, m;
    57         scanf("%d", &n);
    58         for ( int i = 1; i <= n; i++ )
    59         {
    60             c[i] = 1;
    61         }
    62         for ( int i = 1; i <= n; i++ )
    63         {
    64             scanf("%d", a + i);
    65             update( i, a[i] );
    66         }
    67         scanf("%d", &m);
    68         while ( m-- )
    69         {
    70             int op, x, y, inv, useless;
    71             scanf("%d%d%d", &op, &x, &y );
    72             if ( op == 0 )
    73             {
    74                 extgcd( get( x - 1 ), MOD, inv, useless );
    75                 inv = ( inv + MOD ) % MOD;
    76                 int tmp = ( ll ) inv * get(y) % MOD;
    77                 printf("%d
    ", tmp);
    78             }
    79             else
    80             {
    81                 extgcd( a[x], MOD, inv, useless );
    82                 inv = ( inv + MOD ) % MOD;
    83                 inv = ( ll ) inv * y % MOD;
    84                 a[x] = ( ll ) a[x] * inv % MOD;
    85                 update( x, inv );
    86             }
    87         }
    88     }
    89     return 0;
    90 }
  • 相关阅读:
    xUtils
    android各类开发框架汇总
    The connection to adb is down, and a severe error has occured.问题解决
    android系统自带主题和自定义主题
    gson处理json和java对象互转
    android解析json数据
    andrid源码目录分析
    JavaScript学习笔记(1)字符串方法
    0day学习笔记(3)Windows定位API引起的惨案(原理)
    内存分页
  • 原文地址:https://www.cnblogs.com/huoxiayu/p/4692270.html
Copyright © 2011-2022 走看看