【模板】線段樹(&離散化)
阿新 • • 發佈:2022-02-20
#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; }