蓝桥杯_法训练—操作格子(线段树点更新与区间查询)
2017-07-08 19:12
573 查看
Description
有n个格子,从左到右放成一排,编号为1-n。共有m次操作,有3种操作类型:
1.修改一个格子的权值,
2.求连续一段格子权值和,
3.求连续一段格子的最大值。
对于每个2、3操作输出你所求出的结果。
Input
多组测试数据第一行2个整数n,m。
接下来一行n个整数表示n个格子的初始权值。
接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。
Output
每组测试数据输出有若干行,行数等于p=2或3的操作总数。每行1个整数,对应了每个p=2或3操作的结果。
Sample Input
![](http://acm.wust.edu.cn/image/copy.gif)
4 3 1 2 3 4 2 1 3 1 4 3 3 1 4
Sample Output
6 3
题意很明确,就是线段树的单点更新,也没有什么坑,只要注意一些细节就好,数组也不是很大,好过。
【代码】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=100010;
int m,n;
int a
,s,maxm;
struct tree
{
int l,r,sum,maxn;
}Node[N*4];
int max(int x,int y)
{
return x>y?x:y;
}
void build_tree(int ans,int ll,int rr)
{
if(ll == rr)
{
Node[ans].l =Node[ans].r = ll;
Node[ans].sum = Node[ans].maxn= a[ll];
return ;
}
int mid = (ll + rr )>>1;
Node[ans].l = ll;
Node[ans].r = rr;
build_tree(ans<<1,ll,mid);
build_tree(ans<<1|1,mid+1,rr);
Node[ans].sum = Node[ans<<1].sum + Node[ans<<1|1].sum;
Node[ans].maxn = max(Node[ans<<1].maxn , Node[ans<<1|1].maxn);
}
void update(int ans,int w,int value)
{
if(Node[ans].l == w&& Node[ans].r == w )
{
Node[ans].sum= value;
Node[ans].maxn = value;
return ;
}
int mid = (Node[ans].l+Node[ans].r)>>1;
if(w<=mid)
{
update(ans<<1,w,value);
}
cd8d
else
{
update(ans<<1|1,w,value);
}
Node[ans].sum = Node[ans<<1].sum + Node[ans<<1|1].sum;
Node[ans].maxn = max(Node[ans<<1].maxn,Node[ans<<1|1].maxn);
}
void query(int ans,int ll,int rr)
{
int mid = (Node[ans].l+Node[ans].r)>>1;
if(Node[ans].l== ll&& Node[ans].r== rr)
{
s+=Node[ans].sum;
return ;
}
if(rr<=mid)
{
query(ans<<1,ll,rr);
}
else if(ll>mid)
{
query(ans<<1|1,ll,rr);
}
else
{
query(ans<<1,ll,mid);
query(ans<<1|1,mid+1,rr);
}
}
int query_max(int ans,int ll,int rr)
{
int mid = (Node[ans].l+Node[ans].r)>>1;
if(Node[ans].l == ll && Node[ans].r == rr)
{
return Node[ans].maxn;
}
if(Node[ans].l==Node[ans].r)
return 0;
if(rr<=mid)
{
query_max(ans<<1,ll,rr);
}
else if(ll>mid)
query_max(ans<<1|1,ll,rr);
else
{
return max(query_max(ans<<1,ll,mid),query_max(ans<<1|1,mid+1,rr));
}
//printf("%d\n",maxm);
}
int main()
{
while(~scanf("%d%d",&m,&n)){
for(int i=1;i<=m;i++)
scanf("%d",&a[i]);
build_tree(1,1,m);
while(n--)
{
int x,aa,bb;
scanf("%d",&x);
if(x==1)
{
scanf("%d%d",&aa,&bb);
update(1,aa,bb);
}
else if(x==2)
{
s=0;
scanf("%d%d",&aa,&bb);
query(1,aa,bb);
printf("%d\n",s);
}
else
{
scanf("%d%d",&aa,&bb);
printf("%d\n",query_max(1,aa,bb));
}
}
}
}
代码写的还不熟练,有的地方比较繁琐,不过我觉得这样反而更容易懂。
相关文章推荐
- 蓝桥杯算法训练——操作格子(线段树+单点更新+区间求和+求最大值)
- 蓝桥杯算法训练_格子操作_线段树_区间和与区间最值
- 蓝桥 操作格子 线段树 单点更新 区间查询
- 蓝桥杯 算法训练 操作格子(线段树,点更新)
- 蓝桥杯 操作格子(线段树更新,求和,求最大)
- Necklace (线段树单点更新+区间查询+离线操作)
- 蓝桥杯 算法训练 操作格子 (线段树)
- 算法训练 操作格子 线段树 单点修改,求区间和,区间最大值
- 线段树基础操作--单点or区间更新+查询
- 蓝桥杯 算法训练 操作格子 [ 线段树 ]
- [蓝桥杯]算法训练 操作格子-链式线段树
- 蓝桥杯 操作格子(线段树的更新)
- 蓝桥杯 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子 (最基本的线段树)
- HDU 3874 Necklace (线段树单点更新+区间查询+离线操作)
- 蓝桥杯 ALGO-8 算法训练 操作格子(线段树)
- 蓝桥杯 算法训练 操作格子 (线段树模板)
- HDU 3308 线段树 最长连续上升子序列 单点更新 区间查询
- HDU 4267 线段树 离散点区间更新, 自叶子节点至根单点查询
- 蓝桥杯-算法训练之区间K大数查询——ALGO-1