zoukankan      html  css  js  c++  java
  • 【OI】指针线段树&指针

    对于线段树,我们一般需要n*4的空间去存储线段树,然后有一种玄学操作是用指针来实现线段树。

    #include <inttypes.h>
    #include <algorithm>
    #include <cstdio>
    #include <iostream>
    #include <vector>
    #define debug(x) std::cout<< #x << " = " << std::endl;
    
    typedef long long int int_t;
    
    using std::cin;
    using std::cout;
    using std::endl;
    
    struct Node{
        
        Node *left,*right;
        int_t value;
        int begin,end;
        int mark;
        Node(int begin, int end) {
            this->begin = begin;
            this->end = end;
            left = right = NULL;
            mark = 0; 
        }
        
        void add(int_t val) {
            this->value += (end - begin + 1) * val;
            mark += val;
        }
        
        void maintain() {
            if(begin != end) {
                this->value = left -> value + right->value;
                
            }
            
            
        }
        
        void pushDown(){
            if (mark) {
                
                if(begin!= end) {
                    left -> add(mark);
                    right -> add(mark);
                    
                }
                mark = 0;
            }
        }
        
        int_t query (int begin,int end){
            if(end < this->begin || begin > this->end) return 0;
            if(this->begin >= begin && this->end <= end) return this->value;
            this->pushDown();
            return left->query(begin,end) + right->query(begin, end) ;    
         
         }
         
         void add(int begin,int end,int_t val){
             if(end < this->begin || begin > this->end) return;
             if(this->begin >= begin && this->end <= end) {
                 this->add(val);
                 return ;
             }
             this->pushDown();
             left->add(begin,end,val);
             right->add(begin,end,val);
             this->maintain();
         }
        
        
    };
    char buf[400010*sizeof(Node)];
    int used = 0;
    
    void* allocate() { return (++used) * sizeof(Node) + buf;}
    
    const int MaxN = 200010;
    Node* tree;
    int_t a[MaxN];
    int n,m;
    
    Node* build(int begin,int end){
        int mid = (begin + end)/2;
        
        Node* node = new(allocate()) Node(begin,end);
        if(begin != end){
            node->left = build(begin ,mid);
            node->right = build(mid+1,end);
            
            
        }
        
        else if(begin == end){
            node->value = a[begin];
        }
        
        node->maintain();
        return node;
    }
    
    
    
    
    int main(){
        scanf("%d%d",&n,&m);
        
        for(int i = 1; i <= n; i++){
            scanf("%lld",&a[i]);
        }
        
        tree = build(1,n);
        
        
        for(int i = 1; i <= m; i++){
            int opt,x,y;
            int_t k;
            scanf("%d",&opt);
            if(opt == 1){
                scanf("%d%d%lld",&x,&y,&k);
                tree->add(x,y,k);
                
            }
            else
            {
                scanf("%d%d",&x,&y);
                
                printf("%lld
    ",tree->query(x,y));
            }
        }
        
        return 0;
    }
    Code

    接着这个代码说一下指针:

    声明指针的方法是 type *x;

    例如 int* a;

    这样就是声明了一个int类型的指针,没有指向任何的内存。

    然后,可以使用 int* a = NULL; 来初始化它,这时候它是一个空指针,一旦对它试图对它操作就会RE,比如 int* a = NULL;

    指针本质上一个存贮8比特地址的整形变量,所以应该使用取地址符&来给指针赋值:

    int c;

    int *a = &c;

    我们要通过指针给原本元素赋值:

    int c = 0;

    int *a = &c;

    *a = 5;

    这时输出c的值为5

    另一种写法是引用,相当于给了某个变量另一个名字,本质仍然是存储地址。

    int c = 0;

    int &a = c;

    a = 5;

     与上面的写法是一样的效果。

    指针不一定要指向某个变量,可以直接指向某个内存空间。

    例如,我声明了一个结构体 struct custom{int a,b;};

    然后,我们就可以使用指针指向内存中一个custom类型的内存,例如 custom* cs = new custom;

    通过new关键字为这个指针创建一块内存,这个指针就指向它。

    但是,如果想访问这个结构体的成员,则不同于原来的 "."访问,需要用 "->"来访问成员。

    例如, cs->a = 0; 这样就算是给这个指针指向的结构体内存的a成员赋值为0。

    但是,new是系统自动为其分配内存,比较慢,所以我们就可以创建一块内存池: char buf[400010*sizeof(custom)];

    然后,用一个变量记录已经使用了内存池中的多少内存:int used = 0;

    定义向这个内存池分配内存的函数:void* allocate() { return (++used) * sizeof(custom) + buf;}

    used每次加1,记录已经使用了used个大小为sizeof(custom)的内存,然后加号后面是创建的内存池。

    于是就可以使用这个内存池来分配内存:

    custom *cs;

    cs = new(allocate()) custom;

    类型后面可以跟上构造函数,假设我们的custom有这样的构造函数:

    custom(int a,int b){this->a = a;this->b = b;}

    于是分配内存时就可以这样写:cs = new(allocate()) custom(1,2);

  • 相关阅读:
    线性可分支持向量机
    谈对牛顿法的理解
    最大熵模型学习笔记
    Maven --- <distributionManagement>标签
    poi-word导出,导出多图片到word
    poi-excel导入导出
    ApplicationContextInitializer接口
    springboot伪静态
    springboot集成邮件服务
    多文件上传demo
  • 原文地址:https://www.cnblogs.com/dudujerry/p/10422864.html
Copyright © 2011-2022 走看看