线段树(单点修改,区间查询)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/algzjh/article/details/76687295
/*
 * 线段树模板
 * 单点修改,区间查询
 */
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MAXN=1e5+5;//
const int INF=0x3f3f3f3f;//根据是否超long long修改
int a[MAXN];

//线段树节点结构体
struct Node{
    int left,right;//左右边界
    int mi,ma;//最小值 最大值
    LL sum;//和
}tree[MAXN*4];//空间开四倍

//向上更新
void PushUp(int rt){
    tree[rt].mi=min(tree[rt<<1].mi,tree[rt<<1|1].mi);
    tree[rt].ma=max(tree[rt<<1].ma,tree[rt<<1|1].ma);
    tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
}

//建立函数
void Build(int rt,int L,int R){
    tree[rt].left=L;tree[rt].right=R;
    if(L==R) {tree[rt].sum=tree[rt].mi=tree[rt].ma=a[L]; return;}
    int mid=(tree[rt].left+tree[rt].right)>>1;
    Build(rt<<1,L,mid);//只有Build时LR才会变
    Build(rt<<1|1,mid+1,R);
    PushUp(rt);
}

LL QuerySum(int rt,int L,int R){
    if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].sum;//贡献为tree[rt].sum
    int mid=(tree[rt].left+tree[rt].right)>>1;
    LL res=0;
    if(L<=mid) res+=QuerySum(rt<<1,L,R);
    if(R>mid)  res+=QuerySum(rt<<1|1,L,R);
    return res;
}

int QueryMin(int rt,int L,int R){
    if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].mi;
    int mid=(tree[rt].left+tree[rt].right)>>1;
    int res=INF;
    if(L<=mid) res=min(res,QueryMin(rt<<1,L,R));
    if(R>mid)  res=min(res,QueryMin(rt<<1|1,L,R));
    return  res;
}

int QueryMax(int rt,int L,int R){
    if(L<=tree[rt].left&&tree[rt].right<=R) return  tree[rt].ma;//完全包含才产生贡献
    int mid=(tree[rt].left+tree[rt].right)>>1;
    int res=-INF;
    if(L<=mid) res=max(res,QueryMax(rt<<1,L,R));
    if(R>mid)  res=max(res,QueryMax(rt<<1|1,L,R));
    return  res;
}

void Update(int rt,int pos,int x){//把pos位的值改为x
    if(tree[rt].left==tree[rt].right) { tree[rt].sum=tree[rt].mi=tree[rt].ma=x; return; }
    int mid=(tree[rt].left+tree[rt].right)>>1;
    if(pos<=mid) Update(rt<<1,pos,x);
    else Update(rt<<1|1,pos,x);
    PushUp(rt);
}

int main() {
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        Build(1,1,n);//建立线段树
        int op,x,y;
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&op,&x,&y);
            if(op==1){//询问[x,y]的和
                printf("%lld\n",QuerySum(1,x,y));
            }else if(op==2){//询问[x,y]的最大值
                printf("%d\n",QueryMax(1,x,y));
            }else if(op==3){//询问[x,y]的最小值
                printf("%d\n",QueryMin(1,x,y));
            }else{//修改第x位的值为y
                Update(1,x,y);
            }
        }
    }
    return 0;
}
/*
6 4
1 2 3 4 5 6
4
3 8
1
1 6
2
1 6
3
1 6
 */
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long LL;
const int MAXN=2e5+5;
int val[MAXN];

struct node
{
    int ma,left,right;
}tree[MAXN*4];

void pushup(int rt)
{
    tree[rt].ma=max(tree[lson].ma,tree[rson].ma);
}

void build(int rt,int left,int right)
{
    tree[rt].left=left;
    tree[rt].right=right;
    if(left==right) {tree[rt].ma=val[left];return;}
    int mid=(left+right)>>1;
    build(lson,left,mid);
    build(rson,mid+1,right);
    pushup(rt);
}

int query(int rt,int left,int right)
{
    if(left<=tree[rt].left&&tree[rt].right<=right) return tree[rt].ma;
    int m=(tree[rt].left+tree[rt].right)>>1;
    int res=0;
    if(left<=m) res=max(res,query(lson,left,right));
    if(right>m) res=max(res,query(rson,left,right));
    return res;
}

void update(int rt,int pos,int val)
{
    if(tree[rt].left==tree[rt].right) {tree[rt].ma=val;return;}
    int m=(tree[rt].left+tree[rt].right)>>1;
    if(pos<=m) update(lson,pos,val);
    else update(rson,pos,val);
    pushup(rt);
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;++i)
            scanf("%d",&val[i]);
        build(1,1,n);
        for(int i=1;i<=m;++i)
        {
            getchar();
            char op;int x,y;
            scanf("%c",&op);
            scanf("%d%d",&x,&y);
            if(op=='Q')
            {
                printf("%d\n",query(1,x,y));
            }else
            {
                update(1,x,y);
            }
        }
    }
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const double eps=1e-10;
const int MAXN=1e5+5;
const int MOD=1e9+7;
int a[MAXN];
int minv[MAXN*4];

void build(int l,int r,int rt)
{
    if(l==r) {minv[rt]=a[l];return;}
    int m=l+(r-l)/2;
    build(l,m,rt*2);
    build(m+1,r,rt*2+1);
    minv[rt]=min(minv[rt*2],minv[rt*2+1]);
}

int query(int o,int L,int R,int ql,int qr)
{
    int M=L+(R-L)/2,ans=INF;
    if(ql<=L&&R<=qr) return minv[o];//当前结点完全包含在查询区间内
    if(ql<=M) ans=min(ans,query(o*2,L,M,ql,qr));//往左走
    if(M<qr) ans=min(ans,query(o*2+1,M+1,R,ql,qr));//往右走
    return ans;
}

void update(int o,int L,int R,int p,int v)//修改A[p]=v
{
    int M=L+(R-L)/2;
    if(L==R) minv[o]=v;//叶结点,直接更新minv
    else
    {
        if(p<=M) update(o*2,L,M,p,v);
        else update(o*2+1,M+1,R,p,v);
        minv[o]=min(minv[o*2],minv[o*2+1]);
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
        build(1,n,1);
        int q;
        scanf("%d",&q);
        int op,x,y;
        for(int i=1;i<=q;++i)
        {
            cin>>op>>x>>y;
            if(op==1)
            {
                update(1,1,n,x,y);
            }else if(op==2)
            {
                cout<<query(1,1,n,x,y)<<endl;
            }
        }
    }
    return 0;
}
/*
10
10
1 2 3 4 5 6 7 8 9 10
100
1 1 2
*/

没有更多推荐了,返回首页