您的位置:首页 > 理论基础 > 数据结构算法

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

2015-04-18 01:21 344 查看

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]这个区间的元素和

1≤n,m,v,ai≤100000,1≤l≤r≤n。

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。

代码:

# include<cstdio>
# include<iostream>
# include<fstream>
# include<algorithm>
# include<functional>
# include<cstring>
# include<string>
# include<cstdlib>
# include<iomanip>
# include<numeric>
# include<cctype>
# include<cmath>
# include<ctime>
# include<queue>
# include<stack>
# include<list>
# include<set>
# include<map>

using namespace std;

const double PI=4.0*atan(1.0);

typedef long long LL;
typedef unsigned long long ULL;

# define inf 999999999
# define MAX 100004

struct Segtree
{
int left, right;
LL sum;
}tree[MAX*4];

int a[MAX];

void build ( int id,int l,int r )
{
tree[id].left = l; tree[id].right = r;
if ( l==r )
{
scanf("%lld",&tree[id].sum);
return;
}
else
{
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
}

}

void updata( int id,int pos,int val )
{
if ( tree[id].left==tree[id].right )
{
tree[id].sum = val;
}
else
{
int mid = ( tree[id].left+tree[id].right )>>1;
if ( pos <= mid )
{
updata( id<<1,pos,val );
}
else
{
updata( id<<1|1,pos,val );
}
tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
}
}

LL query( int id,int l,int r )
{
if ( tree[id].left==l&&tree[id].right==r )
{
return tree[id].sum;
}
else
{
int mid = ( tree[id].left+tree[id].right )>>1;
if ( r <= mid )
{
query( id<<1,l,r );
}
else if ( l > mid )
{
query( id<<1|1,l,r );
}
else
{
return query( id<<1,l,mid)+query( id<<1|1,mid+1,r );
}
}
}

int main(void)
{
int n;
while ( cin>>n )
{
memset(tree,0,sizeof(tree));
build(1,1,n);
int t;cin>>t;
while ( t-- )
{
int t1,a,b;
cin>>t1>>a>>b;
if ( t1==1 )
{
updata(1,a,b);
}
else
{
cout<<query(1,a,b)<<endl;
}
}
}

return 0;
}


第二种写法:

区别就是对于原数组的处理,感觉第二种更能接受一点。

# include<cstdio>
# include<iostream>
# include<fstream>
# include<algorithm>
# include<functional>
# include<cstring>
# include<string>
# include<cstdlib>
# include<iomanip>
# include<numeric>
# include<cctype>
# include<cmath>
# include<ctime>
# include<queue>
# include<stack>
# include<list>
# include<set>
# include<map>

using namespace std;

const double PI=4.0*atan(1.0);

typedef long long LL;
typedef unsigned long long ULL;

# define inf 999999999
# define MAX 100004

struct Segtree
{
int left, right;
LL sum;
}tree[MAX*4];

LL a[MAX];

void build ( int id,int l,int r )
{
tree[id].left = l; tree[id].right = r;
if ( l==r )
{
tree[id].sum = a[l];
return;
}
else
{
int mid = (l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
}

}

void updata( int id,int pos,int val )
{
if ( tree[id].left==tree[id].right )
{
tree[id].sum = val;
}
else
{
int mid = ( tree[id].left+tree[id].right )>>1;
if ( pos <= mid )
{
updata( id<<1,pos,val );
}
else
{
updata( id<<1|1,pos,val );
}
tree[id].sum = tree[id<<1].sum+tree[id<<1|1].sum;
}
}

LL query( int id,int l,int r )
{
if ( tree[id].left==l&&tree[id].right==r )
{
return tree[id].sum;
}
else
{
int mid = ( tree[id].left+tree[id].right )>>1;
if ( r <= mid )
{
query( id<<1,l,r );
}
else if ( l > mid )
{
query( id<<1|1,l,r );
}
else
{
return query( id<<1,l,mid)+query( id<<1|1,mid+1,r );
}
}
}

int main(void)
{
int n;
while ( cin>>n )
{
for ( int i = 1;i <= n;i++ )
{
scanf("%lld",&a[i]);
}
memset(tree,0,sizeof(tree));
build(1,1,n);
int t;cin>>t;
while ( t-- )
{
int t1,a,b;
cin>>t1>>a>>b;
if ( t1==1 )
{
updata(1,a,b);
}
else
{
cout<<query(1,a,b)<<endl;
}
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐