1. 程式人生 > 其它 >【模板】線段樹(&離散化)

【模板】線段樹(&離散化)

#include<bits/stdc++.h>
using namespace std;
const int the_size = 262144;
int in[the_size], n, m, s, e, v, ans;
char judge;
struct TREE{                                                                //結構體-樹
    int left, right;
    int maxn, sumn, minn;
    int lid, rid;
    int lazy;
    //other information;
} tree[the_size]; int cnt;
int x = 0, f = 1; char c;
inline int g() {                                                            //快讀;
    x = 0; f = 1; c = getchar();
    for(;(c > '9'||c < '0')&&c != '-';c = getchar());
    if(c == '-') { f = -1; c = getchar();}
    for(;c >= '0'&&c <= '9';c = getchar()) x = (x<<3)+(x<<1)+c-'0';
    return x*f;
}//快讀;
inline void discrete(int *a,const int k) {                                  //離散化;
    int data[the_size];
    for(register int i = 1;i <= k;i++) data[i] = a[i];
    sort(data+1,data+k+1);
    int cc = unique(data+1,data+k+1)-data;
    for(register int i = 1;i <= k;i++) {
        a[i] = lower_bound(data+1,data+cc,a[i])-data;
    }
    return;
}//離散化;
inline void construct(const int id,const int l,const int r) {               //建樹;
    tree[id].left = l; tree[id].right = r;
    if(l == r) {
        tree[id].minn = in[l];
        tree[id].maxn = in[l];
        tree[id].sumn = in[l];
        return;
    }//if is leaf;
    int mid = (l+r)/2;      //the middle point;
    tree[id].lid = ++cnt; tree[id].rid = ++cnt;
    construct(tree[id].lid,l,mid);  //build the left son_tree;
    construct(tree[id].rid,mid+1,r); //build the right son_tree;
    tree[id].minn = min(tree[tree[id].lid].minn,tree[tree[id].rid].minn);   //preserve the minn;
    tree[id].sumn = tree[tree[id].lid].sumn+tree[tree[id].rid].sumn;        //preserve the sumn;
    tree[id].maxn = max(tree[tree[id].lid].maxn,tree[tree[id].rid].maxn);   //preserve the maxn;
    return;
}//建樹;
inline void pushdown(const int id) {                                        //下放;
    tree[tree[id].lid].lazy += tree[id].lazy;//perserve the sign of pushdown(lazy);
    tree[tree[id].rid].lazy += tree[id].lazy;//perserve the sign of pushdown(lazy);
    tree[tree[id].lid].sumn += tree[id].lazy*(tree[tree[id].lid].right-tree[tree[id].lid].left+1);//preserve the sumn;
    tree[tree[id].rid].sumn += tree[id].lazy*(tree[tree[id].rid].right-tree[tree[id].rid].left+1);//preserve the sumn;
    tree[id].lazy = 0;
    return;
}//下放;
inline void pushup(const int id) {                                          //上傳;
    tree[id].sumn = tree[tree[id].lid].sumn+tree[tree[id].rid].sumn;        
    tree[id].maxn = max(tree[tree[id].lid].maxn,tree[tree[id].rid].maxn);   
    tree[id].minn = min(tree[tree[id].lid].minn,tree[tree[id].rid].minn);   
    return;
}//上傳;
inline void update(const int id,const int l,const int r,const int val) {    //區間修改;
    if(tree[id].left == l&&tree[id].right == r) {
        tree[id].lazy += val;
        tree[id].sumn += val*(tree[id].right-tree[id].left+1);
        tree[id].maxn += val;
        tree[id].minn += val;
        return;
    }//if is leaf;
    pushdown(id);//pushdown;
    int mid = (tree[id].left+tree[id].right)>>1;    //find the middle point;
    if(r <= mid) update(tree[id].lid,l,r,val);      //if is left son_tree;
    else if(l > mid) update(tree[id].rid,l,r,val);  //if is right son_tree;
    else {  
        update(tree[id].lid,l,mid,val); 
        update(tree[id].rid,mid+1,r,val);   //zone discover;
    }
    pushup(id);
    return;
}//區間修改;
inline void modify(const int id,const int sec,const int val) {              //修改單點值;
    if(tree[id].left == tree[id].right) {
        tree[id].sumn = tree[id].maxn = val;
        return;
    }//if is leaf;
    int mid = (tree[id].left+tree[id].right)>>1;        //the middle point;
    modify(sec <= mid ? tree[id].lid : tree[id].rid,sec,val);//
    tree[id].sumn = tree[tree[id].lid].sumn + tree[tree[id].rid].sumn;      //preserve the sumn;
    tree[id].maxn = max(tree[tree[id].lid].maxn,tree[tree[id].rid].maxn);   //preserve the maxn;
    return;
}//修改單點值;
inline int query(const int id,const int l,const int r) {                    //區間求和;
    if(tree[id].left == l&&tree[id].right == r) {
        return tree[id].sumn;//if is leaf;
    }
    pushdown(id);
    int mid = (tree[id].left+tree[id].right)>>1;//find the middle point;
    if(r <= mid) return query(tree[id].lid,l,r);    //if is left son_tree;
    else if(l > mid) return query(tree[id].rid,l,r);    //if is right son_tree;
    else return query(tree[id].lid,l,mid)+query(tree[id].rid,mid+1,r);
}//區間求和;
inline int majority(const int id,const int l,const int r) {                 //區間求最大值;
    if(tree[id].left == l&&tree[id].right == r) {
        return tree[id].maxn;//if is leaf;
    }
    pushdown(id);
    int mid = (tree[id].left+tree[id].right)>>1;//find the middle point;
    if(r <= mid) return majority(tree[id].lid,l,r); //if is left son_tree;
    else if(l > mid) return majority(tree[id].rid,l,r); //if is right son_tree;
    else return max(majority(tree[id].lid,l,mid),majority(tree[id].rid,mid+1,r));
}//區間求最大值;
inline int minority(const int id,const int l,const int r) {                 //區間求最小值;
    if(tree[id].left == l&&tree[id].right == r) {
        return tree[id].minn;//if is leaf;
    }
    pushdown(id);
    int mid = (tree[id].left+tree[id].right)>>1;//find the middle point;
    if(r <= mid) return minority(tree[id].lid,l,r); //if is left son_tree;
    else if(l > mid) return minority(tree[id].rid,l,r); //if is right son_tree;
    else return min(minority(tree[id].lid,l,mid),minority(tree[id].rid,mid+1,r));
}//區間求最小值;
inline int point(const int id,const int sec) {                              //查詢單點值
    if(tree[id].left == sec&&tree[id].right == sec) {
        return tree[id].sumn;
    }
    pushdown(id);
    int mid  = (tree[id].left+tree[id].right)>>1;
    if(sec <= mid) return point(tree[id].lid,sec);
    else return point(tree[id].rid,sec);
}//查詢單點值;
int main() {                                                                //主函式;
    //to do;
    return 0;
}