您的位置:首页 > 其它

蓝桥杯_法训练—操作格子(线段树点更新与区间查询)

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 

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));
}
}
}
}


代码写的还不熟练,有的地方比较繁琐,不过我觉得这样反而更容易懂。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: