日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

hdu 3074 线段树 OR 树状数组

發(fā)布時(shí)間:2023/11/29 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 hdu 3074 线段树 OR 树状数组 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

比較基礎(chǔ)的線段樹,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\n", query( 1, a, b )); 93 } 94 else 95 { 96 update( 1, a, b ); 97 } 98 } 99 } 100 return 0; 101 }

?

當(dāng)然,對(duì)于這種單點(diǎn)修改和查詢區(qū)間“前綴和”的問題,我們自然也可以用樹狀數(shù)組來做,不過要用到乘法逆元。

對(duì)于這道題來說,樹狀數(shù)組反而難寫,并且時(shí)間上也沒有什么優(yōu)勢(shì)。

不過這是一種思想,將“加法”擴(kuò)展到了“乘法”。

也可以考慮用log把乘法變成加法,不過可能會(huì)有精度問題。

樹狀數(shù)組:

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\n", 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 }

?

轉(zhuǎn)載于:https://www.cnblogs.com/huoxiayu/p/4692270.html

總結(jié)

以上是生活随笔為你收集整理的hdu 3074 线段树 OR 树状数组的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。