Tido 习题-二叉树-区间查询

题目描述

食堂有N个打饭窗口,现在正到了午饭时间,每个窗口都排了很多的学生,而且每个窗口排队的人数在不断的变化。
现在问你第i个窗口到第j个窗口一共有多少人在排队?

输入

输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是一个正整数N(N<=30000),表示食堂有N个窗口。
接下来一行输入N个正整数,第i个正整数ai表示第i个窗口最开始有ai个人排队。(1<=ai<=50)
接下来每行有一条命令,命令有四种形式:
(1)Add i j,i和j为正整数,表示第i个窗口增加j个人(j不超过30);
(2)Sub i j,i和j为正整数,表示第i个窗口减少j个人(j不超过30);
(3)Query i j,i和j为正整数,i<=j,表示询问第i到第j个窗口的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令。

输出

对于每组输入,首先输出样例号,占一行。
然后对于每个Query询问,输出一个整数,占一行,表示询问的段中的总人数,这个数保持在int以内。

样例输入 Copy

1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End

样例输出 Copy

Case 1:
6
33
59

这一题可以通过线段树来解决
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
const int SIZE=30005;
struct SegmentTree{
    int l,r;
    int dat;
} t[SIZE*4];//struct数组存储线段树
int a[SIZE];
void build(int p,int l,int r){
    t[p].l=l;t[p].r=r;//节点p表示区间l-r
    if(l==r){
        t[p].dat=a[l];
        return;
    }//叶节点
    int mid=(l+r)/2;//折半
    build(p*2,l,mid);//左子节点[l,mid],编号p*2
    build(p*2+1,mid+1,r); //右子节点[mid+1,r],编号p*2+1
    t[p].dat=t[p*2].dat+t[p*2+1].dat;//从下往上传递信息 

}
int ask(int p,int l,int r)//查询区间和
{
    if(l<=t[p].l&&r>=t[p].r)
        return t[p].dat;
    int mid=(t[p].l+t[p].r)/2;
    int val=0;
    if(l<=mid) val+=ask(p*2,l,r);//左子节点有重叠
    if(r>mid) val+=ask(p*2+1,l,r); //右子节点有重叠
    return val;
 }
void change(int p,int x,int v,int xx){//单点修改
    if(t[p].l==t[p].r){//找到叶节点
        if(xx==1)
            t[p].dat+=v;
        if(xx==-1)
            t[p].dat-=v;
        return;
    }
    int mid=(t[p].l+t[p].r)/2;
    if(x<=mid) change(p*2,x,v,xx);//x属于左半区间
    else change(p*2+1,x,v,xx); //x属于右半区间
    t[p].dat=t[p*2].dat+t[p*2+1].dat;//从下往上更新信息
}
int main()
{
    int t;
    cin>>t;
    for(int i=1;i<=t;i++){
        cout<<"Case "<<i<<":"<<endl;
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        build(1,1,n);//建立线段树
        string s;
        while(cin>>s){
            if(s=="End")
                break;
            int a,b;
            cin>>a>>b;
            if(s=="Query")
                cout<<ask(1,a,b)<<endl;
            if(s=="Add")
                change(1,a,b,1);
            if(s=="Sub")
                change(1,a,b,-1);
        }
    }

    return 0;
}
通过线段树可以快速进行单点更新 和 区间求和相当于一个非常巧妙的递归先从上往下到叶节点再将叶节点往上累加再从下回到起点至于线段树的讲解可以先看一下下面的讲解哦https://www.cnblogs.com/Tidoblogs/p/10887555.html

原文地址:https://www.cnblogs.com/Tidoblogs/p/10887599.html

时间: 2024-08-30 14:38:14

Tido 习题-二叉树-区间查询的相关文章

Tido 习题-二叉树-树状数组实现

题目描述 这就是一个简单的树状数组入门题 可以动态地进行区间和查询 随时可能会进行更新   #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> using namespace std; int C[100005]; int n,m; int lowbit(int x){ re

Tido 习题-二叉树-树状数组求逆序对

这里给大家提供一个全新的求逆序对的方法 是通过树状数组来实现的 题目描述   样例输入 Copy 5 2 3 1 5 4 样例输出 Copy 3 提示    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> using namespace std; struct lisan

Tido 习题-二叉树-最高分

题目描述 老师想知道从某某同学到某某同学当中,分数最高的是多少.现在请你编程模拟老师的询问.当然,老师有时候需要更新某位同学的成绩. 输入 输入包含多组测试数据.每组输入第一行是两个正整数N和M(0<N<=30000,0<M<5000),分表代表学生的数目和操作的数目.学生ID编号从1编到N.第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩.接下来有M行.每一行有一个字符C(只取‘Q’或‘U’),和两个正整数A,B.当C为‘Q’的时候,表示这是一条

树和二叉树-第6章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第6章 树和二叉树 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼06 树和二叉树  

[华为机试练习题]42.求二叉树的深度和宽度

题目 题目标题: 求二叉树的宽度和深度 给定一个二叉树,获取该二叉树的宽度和深度. 例如输入 a / b c / \ / d e f g 返回3. 接口说明 原型: int GetBiNodeInfo(BiNode &head, unsigned int *pulWidth, unsigned int *pulHeight) 输入参数: head 需要获取深度的二叉树头结点 输出参数(指针指向的内存区域保证有效): pulWidth 宽度 pulHeight 高度 返回值: 0 成功 1 失败或

二叉树习题

/*编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储). 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树. 建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果. 输入abc##de#g##f###,输出cbegdfa * 1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 typedef struc

习题整理,二叉树后续遍历得到指定节点到其祖先的路径

原文地址:https://www.cnblogs.com/yuelien/p/10051254.html

6-5-树的双亲表示法-树和二叉树-第6章-《数据结构》课本源码-严蔚敏吴伟民版

课本源码部分 第6章  树和二叉树 - 树的双亲表示法 ——<数据结构>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑        本源码引入的文件  链接? Status.h.Scanf.c.SequenceStack.c    

二叉树重建[UVA-536]

二叉树重建Tree Recovery(UVA-536,ULM1997)  时间限制3000ms 分别是书上习题6-3,涉及到二叉树这一数据结构中已知两种遍历求整个树的过程. 首先需要复习一下二叉树的前序遍历和中序遍历和后序遍历.二叉树的前序遍历是指,先输出根结点的值,然后依次递归调用遍历左右子树:中序遍历是指,先递归遍历左子树,然后输出根结点的值,然后递归遍历右子树:后续遍历是指,先递归遍历左右子树,然后输出根结点的值.下面的解题分析都是以此为基础的. 以第一个样例输入为例: 先序遍历:DBAC