数据结构--M - 秋实大哥与线段树(单点更新与区间查询)
M - 秋实大哥与线段树
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
“学习本无底,前进莫徬徨。” 秋实大哥对一旁玩手机的学弟说道。
秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构。
为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来作。
秋实大哥的题目要求你维护一个序列,支持两种操作:一种是修改某一个元素的值;一种是询问一段区间的和。
Input
第一行包含一个整数n,表示序列的长度。
接下来一行包含n个整数ai,表示序列初始的元素。
接下来一行包含一个整数m,表示操作数。
接下来m行,每行是以下两种操作之一:
1 x v : 表示将第x个元素的值改为v
2 l r : 表示询问[l,r]这个区间的元素和
1≤n,m,v,ai≤100000,1≤l≤r≤n。
Output
对于每一个2 l r操作,输出一个整数占一行,表示对应的答案。
Sample input and output
Sample Input | Sample Output |
---|---|
3 1 2 3 3 2 1 2 1 1 5 2 1 2 |
3 7 |
解题思路:
这道题是一道裸裸的线段树的单点更新与区间查询[l,r]sum的问题.
直接套用线段树的模板就可以了,但是要注意long long ,,,因为a_i<=10^5,n<=10^5,且a_i*n<=10^10 > 2*10^9。
代码:
1 # include<cstdio> 2 # include<iostream> 3 # include<fstream> 4 # include<algorithm> 5 # include<functional> 6 # include<cstring> 7 # include<string> 8 # include<cstdlib> 9 # include<iomanip> 10 # include<numeric> 11 # include<cctype> 12 # include<cmath> 13 # include<ctime> 14 # include<queue> 15 # include<stack> 16 # include<list> 17 # include<set> 18 # include<map> 19 20 using namespace std; 21 22 const double PI=4.0*atan(1.0); 23 24 typedef long long LL; 25 typedef unsigned long long ULL; 26 27 # define inf 999999999 28 # define MAX 100004 29 30 struct Segtree 31 { 32 int left, right; 33 LL sum; 34 }tree[MAX*4]; 35 36 int a[MAX]; 37 38 void build ( int id,int l,int r ) 39 { 40 tree[id].left = l; tree[id].right = r; 41 if ( l==r ) 42 { 43 scanf("%lld",&tree[id].sum); 44 return; 45 } 46 else 47 { 48 int mid = (l+r)>>1; 49 build(id<<1,l,mid); 50 build(id<<1|1,mid+1,r); 51 tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum; 52 } 53 54 } 55 56 void updata( int id,int pos,int val ) 57 { 58 if ( tree[id].left==tree[id].right ) 59 { 60 tree[id].sum = val; 61 } 62 else 63 { 64 int mid = ( tree[id].left+tree[id].right )>>1; 65 if ( pos <= mid ) 66 { 67 updata( id<<1,pos,val ); 68 } 69 else 70 { 71 updata( id<<1|1,pos,val ); 72 } 73 tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum; 74 } 75 } 76 77 LL query( int id,int l,int r ) 78 { 79 if ( tree[id].left==l&&tree[id].right==r ) 80 { 81 return tree[id].sum; 82 } 83 else 84 { 85 int mid = ( tree[id].left+tree[id].right )>>1; 86 if ( r <= mid ) 87 { 88 query( id<<1,l,r ); 89 } 90 else if ( l > mid ) 91 { 92 query( id<<1|1,l,r ); 93 } 94 else 95 { 96 return query( id<<1,l,mid)+query( id<<1|1,mid+1,r ); 97 } 98 } 99 } 100 101 102 int main(void) 103 { 104 int n; 105 while ( cin>>n ) 106 { 107 memset(tree,0,sizeof(tree)); 108 build(1,1,n); 109 int t;cin>>t; 110 while ( t-- ) 111 { 112 int t1,a,b; 113 cin>>t1>>a>>b; 114 if ( t1==1 ) 115 { 116 updata(1,a,b); 117 } 118 else 119 { 120 cout<<query(1,a,b)<<endl; 121 } 122 } 123 } 124 125 return 0; 126 }
第二种写法:
区别就是对于原数组的处理,感觉第二种更能接受一点。
1 # include<cstdio> 2 # include<iostream> 3 # include<fstream> 4 # include<algorithm> 5 # include<functional> 6 # include<cstring> 7 # include<string> 8 # include<cstdlib> 9 # include<iomanip> 10 # include<numeric> 11 # include<cctype> 12 # include<cmath> 13 # include<ctime> 14 # include<queue> 15 # include<stack> 16 # include<list> 17 # include<set> 18 # include<map> 19 20 using namespace std; 21 22 const double PI=4.0*atan(1.0); 23 24 typedef long long LL; 25 typedef unsigned long long ULL; 26 27 # define inf 999999999 28 # define MAX 100004 29 30 struct Segtree 31 { 32 int left, right; 33 LL sum; 34 }tree[MAX*4]; 35 36 LL a[MAX]; 37 38 void build ( int id,int l,int r ) 39 { 40 tree[id].left = l; tree[id].right = r; 41 if ( l==r ) 42 { 43 tree[id].sum = a[l]; 44 return; 45 } 46 else 47 { 48 int mid = (l+r)>>1; 49 build(id<<1,l,mid); 50 build(id<<1|1,mid+1,r); 51 tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum; 52 } 53 54 } 55 56 void updata( int id,int pos,int val ) 57 { 58 if ( tree[id].left==tree[id].right ) 59 { 60 tree[id].sum = val; 61 } 62 else 63 { 64 int mid = ( tree[id].left+tree[id].right )>>1; 65 if ( pos <= mid ) 66 { 67 updata( id<<1,pos,val ); 68 } 69 else 70 { 71 updata( id<<1|1,pos,val ); 72 } 73 tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum; 74 } 75 } 76 77 LL query( int id,int l,int r ) 78 { 79 if ( tree[id].left==l&&tree[id].right==r ) 80 { 81 return tree[id].sum; 82 } 83 else 84 { 85 int mid = ( tree[id].left+tree[id].right )>>1; 86 if ( r <= mid ) 87 { 88 query( id<<1,l,r ); 89 } 90 else if ( l > mid ) 91 { 92 query( id<<1|1,l,r ); 93 } 94 else 95 { 96 return query( id<<1,l,mid)+query( id<<1|1,mid+1,r ); 97 } 98 } 99 } 100 101 102 int main(void) 103 { 104 int n; 105 while ( cin>>n ) 106 { 107 for ( int i = 1;i <= n;i++ ) 108 { 109 scanf("%lld",&a[i]); 110 } 111 memset(tree,0,sizeof(tree)); 112 build(1,1,n); 113 int t;cin>>t; 114 while ( t-- ) 115 { 116 int t1,a,b; 117 cin>>t1>>a>>b; 118 if ( t1==1 ) 119 { 120 updata(1,a,b); 121 } 122 else 123 { 124 cout<<query(1,a,b)<<endl; 125 } 126 } 127 } 128 129 return 0; 130 }