zoukankan      html  css  js  c++  java
  • 1. 【线段树】

    题目:第一行输入数字n,第二行输入n个数字。第三行输入数字m,接下来输入m组数据(操作符p,数字x,数字y)。

    其中p=1代表在x位置处+y,p=2对区间(x,y)求和并输出。

    样例:

    输入

    6
    4 5 6 2 1 3
    4
    1 3 5
    2 1 4
    1 1 9
    2 2 6

    输出

    22

    22

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int n,m,p,x,y,ans;//n->数据个数 ,m->修改+查询次数 ,p->操作类型,x,y->操作数,ans->求值 
    struct node
    {
        int l,r,w;//左右边界,权值 
    }tree[400001];
    inline void build(int l,int r,int k)//内联函数,左边界=l,右边界=r,当前节点数=k,根节点序号为1
    {   
    
        tree[k].l=l;tree[k].r=r;//1,1,6 ||2,1,3 ||4,1,2|| 8,1,1||9,2,2||5,3,3||3,4,6||6,4,5||12,4,4||13,5,5||7,6,6(k,l,r)
        if(l==r) //l=r=1||l=r=2 ||l=r=3||l=r=4||l=r=5||l=r=6
        {
            scanf("%d",&tree[k].w);//输入值tree[8].w=4 ||输入值 tree[9].w=5||输入值tree[5].w=6 ||tree[12].w=2||tree[13].w=1||tree[7].w=3
            return ;
        }
        int m=(l+r)/2;//m为中点
        //cout<<"建树过程"<< l<<m<<2*k<<endl;
        
        build(l,m,k*2);//建树(1,3,2) ||建树(1,2,4) ||建树(1,1,8) (此时 l=1,r=2,m=1) ||建树(4,5,6)||建树(4,4,12) 
        //cout<<"建树过程"<< m+1<<r<<2*k+1<<endl;
        build(m+1,r,k*2+1);//树(1,1,8)已经建成返回,开始建树 (2,2,9) ||  建树(3,3,5)||建树(4,6,3) ||建树(5,5,13)||建树(6,6,7) 
        tree[k].w=tree[k*2].w+tree[k*2+1].w;//tree[4].w= 4+5=9||tree[2].w=9+6=15||tree[6].w=2+1=3||tree[3].w=3+3=6||tree[1].w=15+6=21
    }
    inline void add(int k)//k=1,(x=3,y=5)
    {
        if(tree[k].l==tree[k].r)//找到该位置 
        {
            tree[k].w+=y;
            return;
        }
        int m=(tree[k].l+tree[k].r)/2;
        if(x<=m) add(k*2);//x在左树    else add(k*2+1);
        tree[k].w=tree[k*2].w+tree[k*2+1].w; 
    }
    inline void sum(int k)
    {   if(tree[k].l>=x&&tree[k].r<=y) 
        {
            ans+=tree[k].w;
            return;
        }
        int m=(tree[k].l+tree[k].r)/2;
        if(x<=m) sum(k*2);
        if(y>m) sum(k*2+1);
    }
    int main()
    {
        scanf("%d",&n);//输入n个数 
        build(1,n,1);// 建立线段树 
        scanf("%d",&m);//输入操作次数 
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&p,&x,&y);
            ans=0;
            if(p==1) add(1);
            else 
            {
                sum(1);
                printf("%d
    ",ans);
            }
        }
    }

      ps:线段树结构的三个元素为左右边界和权值,真正的数据存储在结点(即左右边界相等的地方),(本题中)其他结点权值存储的是左右孩子的和。从1开始进行双递归建树

    l==r时为输入结点也是递归出口。查询和操作时也是从1开始条件递归操作,注意找到递归出口。

     

  • 相关阅读:
    【 星 辰 · 第 二 条 约 定 】
    【 星 辰 · 第 一 条 约 定 】
    【 塔 · 第 三 条 约 定 】
    【 塔 · 第 二 条 约 定 】
    某些奇葩的正则校验
    localstorage本地存储的简单使用
    js基础(3)之闭包。
    js基础(2)filter()筛选过滤
    js基础(1)变量作用域
    scrum过程
  • 原文地址:https://www.cnblogs.com/apo2019/p/10737585.html
Copyright © 2011-2022 走看看