📜  门| GATE CS 2011 |问题9(1)

📅  最后修改于: 2023-12-03 15:12:36.068000             🧑  作者: Mango

门| GATE CS 2011 |问题9

这是一个GATE CS 2011年考试中的问题9。这个问题比较复杂,但是通过多次练习和思考,我们能够掌握它。

问题描述

你有一个长度为n的正整数序列a,其中每个整数都在1到1000之间。你需要对这个序列进行m次操 作,每个操作都是下面两个操作之一:

1.将a中一个位置上的数加上x。 2.询问a中一段区间[l,r]内的最大值。

解题思路

这道题目我们可以使用线段树来解决。线段树是一种二叉树结构,用于处理区间问题。它非常适合处理这种需要修改区间、查询区间最值的问题。

首先我们需要定义线段树中的节点。每个节点表示一个区间,用[l,r]表示。叶子节点表示a中的一个位置。因此,我们可以使用数组tree[i]来表示线段树中第i个节点。节点i代表区间[l,r],其左儿子为2i,右儿子为2i+1。节点i的值为区间[l,r]内所有的数的最大值。

接下来,我们需要实现两个操作。对于第一个操作,我们可以从根节点开始往下遍历,直到找到需要修改的叶子节点。对于第二个操作,我们需要从根节点开始往下遍历,如果当前节点表示的区间完全包含了我们查询的区间,则直接返回该区间的最大值。否则,我们需要递归地访问该节点的左右儿子,将结果合并起来。

代码实现

下面是代码片段:

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 200200;
const int INF = 0x3f3f3f3f;
int tree[MAXN];
void build(int p,int l,int r){
    if(l==r){
        scanf("%d",&tree[p]);
        return ;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    tree[p]=max(tree[p<<1],tree[p<<1|1]);
}
void update(int p,int l,int r,int x,int y){
    if(l==r){
        tree[p]+=y;
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid){
        update(p<<1,l,mid,x,y);
    } else{
        update(p<<1|1,mid+1,r,x,y);
    }
    tree[p]=max(tree[p<<1],tree[p<<1|1]);
}
int query(int p,int l,int r,int x,int y){
    if(x<=l&&y>=r){
        return tree[p];
    }
    int mid=(l+r)>>1;
    int ans=-INF;
    if(x<=mid){
        ans=max(ans,query(p<<1,l,mid,x,y));
    } if(y>mid){
        ans=max(ans,query(p<<1|1,mid+1,r,x,y));
    }
    return ans;
}
int main(){
    int n,m;
    scanf("%d",&n);
    build(1,1,n);
    scanf("%d",&m);
    while(m--){
        int op;
        scanf("%d",&op);
        if(op==1){
            int x,y;
            scanf("%d%d",&x,&y);
            update(1,1,n,x,y);
        } else{
            int x,y;
            scanf("%d%d",&x,&y);
            printf("%d\n",query(1,1,n,x,y));
        }
    }
}

以上代码是C++实现的。在本代码中,我们使用了四个函数:build、update、query和main。其中,build函数用于初始化线段树;update函数用于修改线段树的某个节点的值;query函数用于查询线段树的一个区间内的最大值;main函数是程序的主函数,用于输入和处理数据。

总结

通过以上的解析和代码实现,我们可以看到线段树着重处理区间问题时的神奇之处。线段树不仅优化了区间查询的时间复杂度,而且非常简单。因此,对于面试和考试中的算法题,我们要熟练掌握线段树这个数据结构。