线段树的实现(求段和)

本文介绍如何使用二分查找与线段树解决区间更新与查询问题,包括构造线段树、插入值和求点集和的操作,以及算法的时间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

View Code
  1 #include<iostream>
  2 #include<stdio.h>
  3 using namespace std;
  4 struct node{
  5        int r;           //root to the right's range
  6        int l;
  7        node * rt;        //the subtree of root's right
  8        node * lt;
  9        __int64 key;         //the value of the root, means the sum of all the leaves of the root
 10 };
 11 node * buildtree(int left,node * root,int right){           //build a tree than can from left to right
 12      root->l=left;
 13      root->r=right;
 14      int temp=(left+right)/2;
 15      if(left==right){                        //build the leaf of the tree
 16           root->lt=NULL;
 17           root->rt=NULL;
 18           root->key=0;                          //made the key of root to 0
 19           return root;
 20           }
 21      else {
 22           node * newleft;
 23           newleft=new node;
 24           root->lt=newleft;
 25           root->key=0;
 26           buildtree(left,newleft,temp);            // constract the left subtree of root
 27           node * newright;
 28           newright=new node;
 29           root->rt=newright;
 30           root->key=0;
 31           buildtree(temp+1,newright,right);          //constract the right subtree of the root
 32           }
 33      return root;
 34 }     
 35 __int64 insert(int point,node * root1,int real){         //insert a value real to a leaf point and sum up to the while tree 
 36      int temp1=(root1->l+root1->r)/2;
 37      long long re1=0,re2=0;
 38      if(point==root1->l&&point==root1->r){
 39              root1->key+=real;
 40              return root1->key;
 41              }
 42      else if(point>=root1->l&&point<=temp1){
 43           re1=insert(point,root1->lt,real);
 44           root1->key=(re1+(root1->rt->key));
 45           return root1->key;
 46           }
 47      else {
 48           re2=insert(point,root1->rt,real);
 49           root1->key=(re2+(root1->lt->key));
 50           return root1->key;
 51           } 
 52 }
 53 __int64 findsum(int left1,int right1,node * root3){             //find the sum of value from left leaf to right leaf
 54      if(left1==root3->l&&right1==root3->r){
 55           return root3->key;
 56           }
 57      __int64 temp3;
 58      int temp2=(root3->l+root3->r)/2;
 59      if(left1>=root3->l&&right1<=temp2){
 60            temp3=findsum(left1,right1,root3->lt);
 61            }
 62      else if(left1>=temp2+1&&right1<=root3->r){
 63            temp3=findsum(left1,right1,root3->rt);
 64            }
 65      else if(left1<=temp2&&right1>=temp2+1){
 66            temp3=findsum(left1,temp2,root3->lt)+findsum(temp2+1,right1,root3->rt);
 67            return temp3;
 68            }
 69      return temp3;
 70 }
 71 int main(){
 72     int n1,n2;
 73     while(scanf("%d%d",&n1,&n2)!=EOF){
 74         node * newtree;
 75         newtree=new node;                 //build a root
 76         buildtree(1,newtree,n1);           // build a tree
 77         for(int g=1;g<=n1;g++){
 78                 int tep3;
 79                 getchar();
 80                 scanf("%d",&tep3);         
 81                 insert(g,newtree,tep3);          //insert a value to the leaf
 82                 }
 83         for(int i=1;i<=n2;i++){
 84                 char temp4;
 85                 getchar();
 86                 scanf("%c",&temp4);
 87                 if(temp4=='C'){
 88                      int temp5,temp7;
 89                      getchar();
 90                      scanf("%d%d",&temp5,&temp7);
 91                      insert(temp5,newtree,temp7);           //insert the value temp7 to the leaf point temp7
 92                              }
 93                 else if(temp4=='Q'){
 94                      getchar();
 95                      int tep1,tep2;
 96                      scanf("%d%d",&tep1,&tep2);
 97                      __int64 tep5=findsum(tep1,tep2,newtree);         //find tne sum of leaf from tep1 to tmp2
 98                      printf("%I64d\n",tep5);
 99                      }
100                 }
101         getchar();
102                 }
103     return 0;
104 }

线段数主要用于更新的值影响区间的值,以及常常要求查找区间的性质时,为节省时间用到的结构。
其中二分的思想十分重要

描述:

     输入点集数以及要求数。

     C a b 为将b值加入到叶子节点a中,

     Q a b 为求点集a到b的总和。

方法:

     建立一棵二叉平衡树。每一个节点都表示以其为根的叶子节点的值的总和。

     所以针对该题,该二叉树有三个操作:构造树(根据一开始的要求,即一共有多少个点集来构造);插入值(将值加到对应的叶子节点中,并且返回时更新根节点的值);求点集的和(在二叉树中找到对应的要求点集的根节点,有可能需要将要求分段查找,然后相加)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值