数据结构--M - 秋实大哥与线段树(单点更新与区间查询)

M - 秋实大哥与线段树

Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
Submit Status

“学习本无底,前进莫徬徨。” 秋实大哥对一旁玩手机的学弟说道。

秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构。

为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来作。

秋实大哥的题目要求你维护一个序列,支持两种操作:一种是修改某一个元素的值;一种是询问一段区间的和。

Input

第一行包含一个整数n,表示序列的长度。

接下来一行包含n个整数ai,表示序列初始的元素。

接下来一行包含一个整数m,表示操作数。

接下来m行,每行是以下两种操作之一:

1 x v : 表示将第x个元素的值改为v 2 l r : 表示询问[l,r]这个区间的元素和

1nmvai1000001lrn

Output

对于每一个2 l r操作,输出一个整数占一行,表示对应的答案。

Sample input and output

Sample InputSample 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 }

 

转载于:https://www.cnblogs.com/wikioibai/p/4436470.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值