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

来源:互联网 发布:甜虾 知乎 编辑:程序博客网 时间:2024/06/05 13:21

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 31 2 3 42 1 31 4 33 1 4

Sample Output

63

   题意很明确,就是线段树的单点更新,也没有什么坑,只要注意一些细节就好,数组也不是很大,好过。

  【代码】

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=100010;int m,n;int a[N],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);    }    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));        }    }    }}

代码写的还不熟练,有的地方比较繁琐,不过我觉得这样反而更容易懂。


阅读全文
1 0
原创粉丝点击