dalao求跳,有赏,私信

P3372 【模板】线段树 1

jhhh @ 2024-09-07 17:01:17

#include<bits/stdc++.h>
using namespace std;
struct node { //定义一个块,用来存数据
    int num;//该块的值的和
    int ll,rr;//存储我的下标
    node *l,*r;//左子块,右子块
};
node *temp;//临时指针,用来记录我的一个子节点
//建树
bool build(int listt[],int l,int r) { //该序列的数组,左下标,右下标
//  if(l>r)return 0;
    if(l==r) {
        node* t=new(node);//建立一个新节点
        t->num=listt[l];
        t->ll=l;
        t->rr=r;
        t->l=NULL;
        t->r=NULL;
        temp=t;
        return 1;
    }
    node* me=new(node);//建立一个块,是我自己,因为我们区间不会重复选中
    me->num=0;
    me->ll=l;
    me->rr=r;
    int mid=(l+r)/2;//取中间值,划分成两个区间
    if(build(listt,l,mid)) {
        me->l=temp;
        me->num+=temp->num;
    }
    if(build(listt,mid+1,r)) {
        me->r=temp;
        me->num+=temp->num;
    }
    temp=me;
    return 1;
}
void tree_add(node* tree,int l,int r,int k) { //在某个范围添加值
    printf("%d %d\n",tree->ll,tree->rr); 
    if(tree->ll>tree->rr)return;
    //判断范围,烦
    //l,r是需要操作的区间,如果我不在区间内,不管
    int my_l=tree->ll,my_r=tree->rr;
    //如果我不在区间内
    if(my_l>r||my_r<l)return;
    //左子树在区间内
    int my_sonl,my_sonr;
    if(tree->l!=NULL) {
        my_sonl=tree->l->ll,my_sonr=tree->l->rr;
        if(!(my_sonl>r||my_sonr<l))tree_add(tree->l,l,r,k);
    }
    //右子树在区间内
    if(tree->r!=NULL) {
        my_sonl=tree->r->ll,my_sonr=tree->r->rr;
        if(!(my_sonl>r||my_sonr<l))tree_add(tree->r,l,r,k);
    }
    //我自己加
    tree->num+=(r-l+1)*k;
    return;
}
int tree_query(node* tree,int l,int r) {
    if(l>r)return 0;
    int my_l=tree->ll,my_r=tree->rr;//l,r是需要操作的区间,如果我不在区间内,不管
    if(my_l>r||my_r<l)return 0;
    if(my_l==l&&my_r==r)return tree->num;//我恰好是要找的
    int sum=0;
    //l r是要查询的区间
    //先判断左子树
    int son_l,son_r;
    if(tree->l!=NULL) {
        son_l=tree->l->ll,son_r=tree->l->rr;
        if(l<=son_r) {
            if(r<=son_r) { //整体在本区间内
                sum+=tree_query(tree->l,l,r);
            } else {
                sum+=tree_query(tree->l,l,son_r);
            }
        }
    }
    if(tree->r!=NULL) {
        son_l=tree->r->ll,son_r=tree->r->rr;
        if(r>=son_l) {
            if(l>=son_l) { //整体在本区间内
                sum+=tree_query(tree->r,l,r);
            } else {
                sum+=tree_query(tree->r,son_l,r);
            }
        }
    }
    return sum;
}
int main() {
//  freopen(".out","w",stdout);
    int a[20];
    for(int i=1;i<=5;i++){
        cin>>a[i];
    }
    build(a,1,5);
    tree_add(temp,1,2,1);
    node* t=temp;
    cout<<t->l->l->l->num<<endl;
    return 0;
}

by linanchen @ 2024-09-07 17:05:56

不是动态开点的线段树其实不是很推荐指针的写法,因为位运算的速度也是很快加上指针容易RE,同时大部分人都没怎么写过指针版的线段树(比如说我),想帮忙调却无从下手。


by linanchen @ 2024-09-07 17:07:10

if(my_l==l&&my_r==r)return tree->num;//我恰好是要找的

这句话可能有问题,只要包含在内应该都需要返回


by linanchen @ 2024-09-07 17:12:21

问个问题,您的懒标记在哪里(雾)


|