蓝桥杯 操作格子(线段树)
2018-03-10 11:40
246 查看
问题描述有n个格子,从左到右放成一排,编号为1-n。共有m次操作,有3种操作类型:1.修改一个格子的权值,2.求连续一段格子权值和,3.求连续一段格子的最大值。对于每个2、3操作输出你所求出的结果。输入格式第一行2个整数n,m。接下来一行n个整数表示n个格子的初始权值。接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。输出格式有若干行,行数等于p=2或3的操作总数。每行1个整数,对应了每个p=2或3操作的结果。样例输入4 3
1 2 3 4
2 1 3
1 4 3
3 1 4样例输出6
31 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000
思路:线段树裸题,点更新区间查询.
代码:#include<map>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree
{
int l,r;
int maxx;
long long sum;
}t[400005];
int n,m;
int a[100005];
void build(int i,int l,int r)//建树
{
t[i].l = l;//管辖范围
t[i].r = r;
if(l == r)//底部赋值
{
t[i].maxx = a[l];
t[i].sum = a[l];
return ;
}
int mid = (l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
t[i].maxx = max(t[i<<1].maxx,t[i<<1|1].maxx);//管辖范围内最大值
t[i].sum = t[i<<1].sum+t[i<<1|1].sum;//管辖范围总和
}
void mod(int i,int x,int val)//点更新
{
if(x>t[i].r||x<t[i].l)//不在范围内
return ;
if(t[i].l == t[i].r)//找到了
{
t[i].sum = val;
t[i].maxx = val;
return ;
}
mod(i<<1,x,val);
mod(i<<1|1,x,val);
t[i].maxx = max(t[i<<1].maxx,t[i<<1|1].maxx);//更新
t[i].sum = t[i<<1].sum+t[i<<1|1].sum;
}
long long query_sum(int i,int a,int b)//求区间总和
{
if(a>t[i].r||b<t[i].l)//不在范围内
return 0;
if(t[i].l>= a&&t[i].r<= b)//寻找范围完全包含 管辖范围
return t[i].sum;
return query_sum(i<<1,a,b)+query_sum(i<<1|1,a,b);
}
int query_max(int i,int a,int b)//求区间最大值
{
if(a>t[i].r||b<t[i].l)
return 0;
if(t[i].l>= a&&t[i].r<= b)
return t[i].maxx;
return max(query_max(i<<1,a,b),query_max(i<<1|1,a,b));
}
int main()
{
memset(t,0,sizeof(t));
cin>>n>>m;
for(int i = 1;i<= n;i++)
scanf("%d",&a[i]);
build(1,1,n);
while(m--)
{
int o,a,b;
scanf("%d %d %d",&o,&a,&b);
if(o == 1)
mod(1,a,b);
else if(o == 2)
{
long long ans = query_sum(1,a,b);
printf("%I64d\n",ans);
}
else if(o == 3)
{
int ans = query_max(1,a,b);
printf("%d\n",ans);
}
}
return 0;
}
1 2 3 4
2 1 3
1 4 3
3 1 4样例输出6
31 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000
思路:线段树裸题,点更新区间查询.
代码:#include<map>
#include<cstdio>
#include<vector>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
struct tree
{
int l,r;
int maxx;
long long sum;
}t[400005];
int n,m;
int a[100005];
void build(int i,int l,int r)//建树
{
t[i].l = l;//管辖范围
t[i].r = r;
if(l == r)//底部赋值
{
t[i].maxx = a[l];
t[i].sum = a[l];
return ;
}
int mid = (l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
t[i].maxx = max(t[i<<1].maxx,t[i<<1|1].maxx);//管辖范围内最大值
t[i].sum = t[i<<1].sum+t[i<<1|1].sum;//管辖范围总和
}
void mod(int i,int x,int val)//点更新
{
if(x>t[i].r||x<t[i].l)//不在范围内
return ;
if(t[i].l == t[i].r)//找到了
{
t[i].sum = val;
t[i].maxx = val;
return ;
}
mod(i<<1,x,val);
mod(i<<1|1,x,val);
t[i].maxx = max(t[i<<1].maxx,t[i<<1|1].maxx);//更新
t[i].sum = t[i<<1].sum+t[i<<1|1].sum;
}
long long query_sum(int i,int a,int b)//求区间总和
{
if(a>t[i].r||b<t[i].l)//不在范围内
return 0;
if(t[i].l>= a&&t[i].r<= b)//寻找范围完全包含 管辖范围
return t[i].sum;
return query_sum(i<<1,a,b)+query_sum(i<<1|1,a,b);
}
int query_max(int i,int a,int b)//求区间最大值
{
if(a>t[i].r||b<t[i].l)
return 0;
if(t[i].l>= a&&t[i].r<= b)
return t[i].maxx;
return max(query_max(i<<1,a,b),query_max(i<<1|1,a,b));
}
int main()
{
memset(t,0,sizeof(t));
cin>>n>>m;
for(int i = 1;i<= n;i++)
scanf("%d",&a[i]);
build(1,1,n);
while(m--)
{
int o,a,b;
scanf("%d %d %d",&o,&a,&b);
if(o == 1)
mod(1,a,b);
else if(o == 2)
{
long long ans = query_sum(1,a,b);
printf("%I64d\n",ans);
}
else if(o == 3)
{
int ans = query_max(1,a,b);
printf("%d\n",ans);
}
}
return 0;
}
相关文章推荐
- 蓝桥杯算法训练——操作格子(线段树+单点更新+区间求和+求最大值)
- 蓝桥杯 操作格子(线段树更新,求和,求最大)
- 蓝桥杯操作格子(线段树)
- 蓝桥杯 操作格子(线段树的更新)
- 蓝桥杯 操作格子 (线段树)
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子 (最基本的线段树)
- 蓝桥杯 操作格子(线段树)
- 蓝桥杯 操作格子 线段树
- 蓝桥杯_法训练—操作格子(线段树点更新与区间查询)
- 蓝桥杯 - 操作格子 (线段树)
- 蓝桥杯 操作格子 线段树
- 蓝桥杯 算法训练 操作格子 [ 线段树 ]
- 蓝桥杯-操作格子(线段树)
- [蓝桥杯]算法训练 操作格子-链式线段树
- 蓝桥杯 算法训练 操作格子 (线段树)
- 蓝桥杯算法训练_格子操作_线段树_区间和与区间最值
- 蓝桥杯——操作格子(线段树)
- 蓝桥杯 算法训练 操作格子(线段树,点更新)
- 蓝桥杯:操作格子(线段树)