wu


私信TA

用户名:cncfvc

访问量:227218

签 名:

读研狗没有时间刷题了~~

等  级
排  名 3
经  验 37386
参赛次数 8
文章发表 265
年  龄 25
在职情况 学生
学  校 电子科技大学
专  业 通信工程

  自我简介:

写代码 真好玩 ~

解题思路:


这个题解是我从博客上摘抄下来的 
和大家一起分享
这个题目用到了线段树的知识  因为用普通的循环  我们得到的时间复杂度为O(m*n) 肯定会超时
 
这个题目比较复杂 我写的也不是很好  大家多看几遍  多理解 
个人水平 有限  欢迎批评指正~


所谓的线段树如下图:

每个数的结点 里面包含的是线段  

比如根结点包含的线段范围为[a,b]

那么它的左子结点 包含线段的范围为[a,(a+b)/2]   右子结点包含的线段范围为[(a+b)/2+1,b]

(a+b)/2即为mid,如此这样一直分支下去 直到每个结点中包含的线段成了一个点  线段树便构建好了

QQ截图20171215151025.png
参考代码:

#include <iostream>  
#include <string.h>  
#include <algorithm>  
#include <cstdio>  
#include <math.h>  
using namespace std;  
const int N=100000+10;  
struct Node{  
    int l,r,v;  
}node[N*4]; //线段树的每个节点  其中包括三个参数 l为线段左端点的值 r:线段右端点的值  v:该节点所存储的值 
void Init(int now,int le,int ri){    //构建线段树 并将结点的值初始化全部为0   
      if(le==ri){  
        node[now].l=le;  
        node[now].r=ri;  
        node[now].v=0;  
        return;  
      }//如果线段的左端点==线段的右端点  那么即是最后的叶子结点 return  
      int mid=(le+ri)>>1;  //求出中点
      int ne=now<<1;    //将结点的序号*2;
      Init(ne,le,mid);  //构建左子树
      Init(ne+1,mid+1,ri);  //构建右子树
      node[now].l=le;  //给当前结点的线段左右端点赋值
      node[now].r=ri;  
      node[now].v=0;  //给结点赋值
}  
void insert(int now,int le,int ri,int add){       //在线段树中寻找对应的区间  给对应该区间的结点加上该发的
苹果数,即为在那个结点下的所有的子节点的区间里的小孩均会被发苹果。 (pinrt函数中会提到)
    if(node[now].l==le&&node[now].r==ri){  
        node[now].v+=add;  
        return;  
    }  //给对应该区间的结点加上发的苹果数
    int mid=(node[now].l+node[now].r)>>1;//求出中点  
    int ne=now<<1;  //结点的序号*2,方便构建新的结点
     if(ri<=mid){  
        insert(ne,le,ri,add);  //如果寻找的区间的右端点小于中点 则在左边寻找
     }      
    else if(le>mid){  
         insert(ne+1,le,ri,add);  //反之在右边寻找
    }          
    else  
    {  
        insert(ne,le,mid,add);  //如果横跨两边  左右两边都寻找
        insert(ne+1,mid+1,ri,add);  
    }  
}   
void print(int now){  
    if(node[now].l==node[now].r){  
        cout<<node[now].v<<" ";  
        return;  
        }   //如果是最后的叶子结点 输出小朋友的苹果总数
    int ne=now<<1;  
    //父亲的范围大 包含的儿子结点的区间   所以父亲下面儿子结点也要加上父亲结点被发的苹果数  
    node[ne].v+=node[now].v;  
    print(ne);  
    node[ne+1].v+=node[now].v;  
    print(ne+1);  
}  
int main(){  
    int n,m,i,a,b,c;  
    while(cin>>n>>m){  
        Init(1,1,n);  
        for(i=0;i<m;i++){  
            cin>>a>>b>>c;  
            insert(1,a,b,c);  
        }  
        print(1);  
    }  
    return 0;  
}


 

0.0分

8 人评分

  评论区

线段树优化,真离谱
2022-02-16 15:59:47
棒棒哒!!
2020-07-20 08:06:35
棒棒哒!!
2020-07-20 08:06:19
棒棒哒!!
2020-07-20 08:05:41
棒棒哒!!
2020-07-20 08:05:23
棒棒哒!!
2020-07-20 08:04:48
棒棒哒!!
2020-07-20 08:04:36
棒棒哒!!
2020-07-20 08:04:18