线段树1

问题引入1:长度为N的一维数组(a[1]~a[N]),有q(q <= 100000)次询问,每次询问为l, r,代表区间[l, r]之间数的和。

问题引入2:在问题1的基础上我们再加一种更改操作,也就是每次的操作可能有两种类型,一种是查询操作,询问区间[l, r]之间的数的和,第二种是更新操作,将位置i上的数更改为x。

经典例题:给你一个数组a[1]~a[N],有q次操作,每次操作有两种类型,第一种询问操作,询问区间[l, r]之间数的和,第二种操作是修改操作,将位置loc的数改为x。

#include<bits/stdc++.h>
using namespace std;
struct node{
    int l,r;
    int sum;
}Node[200000];
long long a[100000];
void pushUp(int k)//计算和,从下往上
{
    Node[k].sum=Node[k<<1].sum+Node[(k<<1)+1].sum;
}
void build(int i,int l,int r)
{
    Node[i].l=l;
    Node[i].r=r;
    Node[i].sum=0;
    if(l==r)
    {
        Node[i].sum=a[l];//a[l]是数组中的数
        return ;
    }
    int mid=(l+r)>>1;
    build(i<<1,l,mid);//左儿子
    build((i<<1)+1,mid+1,r);//右儿子
    pushUp(i);
}
void update(int i,int loc,int val)//更新(下标,之前要改的数的下标,要改的数的值)
{
    if(Node[i].l==Node[i].r)
    {
        Node[i].sum=val;
        return;
    }
    int mid=(Node[i].l+Node[i].r)>>1;
    if(loc<=mid) update(i<<1,loc,val);
    else update((i<<1)+1,loc,val);
    pushUp(i);
}
int query(int i,int l,int r)//查询
{
    if(Node[i].l==l && Node[i].r==r)
    {
        return Node[i].sum;
    }
    int mid=(Node[i].l+Node[i].r)>>1;
     if(r<=mid) return query(i<<1,l,r);
     else if(l>mid) return query((i<<1)+1,l,r);
     else
     {
         return query(i<<1,l,mid)+query((i<<1)+1,mid+1,r);
     }
}
int main()
{
    ios::sync_with_stdio(0);
    int T;
    cin>>T;
    for(int i=0;i<T;i++)
    {
        int N,q;
        cin>>N>>q;
        for(int i=1;i<=N;i++)//i=1开始,切记
        {
            cin>>a[i];
        }
        build(1,1,N);
        for(int i=0;i<q;i++)
        {
            int a,b,c;
            cin>>a>>b>>c;
            if(a==1)
            {
                update(1,b,c);
            }
            else if(a==2)
            {
                cout<<query(1,b,c)<<endl;
            }
        }
    }
    return 0;
}

可扩散为判断奇偶数,以及最大最小值

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值