4 數據結構

4 數據結構

4.1 樹狀數組
4.1.1 普通樹狀數組

僅支持單點修改區間查詢。

const int maxn = 1e5 + 10;

int tree[maxn];

int lb(int x) { return x & -x; }

int read(int x) {
    int tot = 0;
    for (int i = x; i; i -= lb(i)) {
        tot += tree[i];
    }
    return tot;
}

void add(int num, int x) {
    for (int i = x; i <= n; i += lb(i)) {
        tree[i] += num;
    }
}

4.1.2 普通二維樹狀數組
const int maxn = 1010;
int tree[maxn][maxn];
int n, m;

int lb(int x) { return x & -x; }

int read(int x, int y) {
    int tot = 0;
    for (int i = x; i; i -= lb(i)) {
        for (int j = y; j; j -= lb(j))
            tot += tree[i][j];
    }
    return tot;
}

void add(int num, int x, int y) {
    for (int i = x; i <= n; i += lb(i)) {
        for (int j = y; j <= m; j += lb(j)) {
            tree[i][j] += num;
        }
    }
}
4.1.3 樹狀數組維護區間最大、最小值

維護區間[1,x]的:

const int maxn = 1e5 + 10;
int c[maxn], n, r[maxn], a[maxn];

inline int lb(int x) { return x & -x; }

int query(int x) {
    int tot = 0;
    for (; x; x -= lb(x))
        tot = max(tot, c[x]);
    return tot;
}

void update(int x, int v) {
    for (; x <= n; x += lb(x)) {
        c[x] = max(c[x], v);
        int t = x - lb(x);
        for (int y = x - 1; y && y - lb(y) >= t; y -= lb(y))
            c[x] = max(c[x], c[y]);
    }
}

4.2 線段樹
4.2.1 維護區間最值,區間修改
const int maxn = 1e5 + 10;
 
struct tree {
    int left, right;
    ll sum, add, maxm, minm;
} c[maxn << 2];
 
ll a[maxn];
 
void build(int id, int l, int r) {
    c[id].left = l;
    c[id].right = r;
    if (l == r) {
        c[id].maxm = c[id].minm = c[id].sum = a[l];
        c[id].add = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(id << 1, l, mid);
    build(id << 1 | 1, mid + 1, r);
    c[id].maxm = max(c[id << 1].maxm, c[id << 1 | 1].maxm);
    c[id].minm = min(c[id << 1].minm, c[id << 1 | 1].minm);
    c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
}
 
void pushdown(int id) {
    c[id << 1].sum += (c[id << 1].right - c[id << 1].left + 1) * c[id].add;
    c[id << 1].minm += c[id].add;
    c[id << 1].maxm += c[id].add;
    c[id << 1].add += c[id].add;
    c[id << 1 | 1].sum += (c[id << 1 | 1].right - c[id << 1 | 1].left + 1) * c[id].add;
    c[id << 1 | 1].minm += c[id].add;
    c[id << 1 | 1].maxm += c[id].add;
    c[id << 1 | 1].add += c[id].add;
    c[id].add = 0;
}
 
void update(int id, int pos, ll v) {
    if (c[id].left == c[id].right)c[id].sum = c[id].maxm = c[id].minm = v;
    else {
        int mid = (c[id].left + c[id].right) >> 1;
        if (pos <= mid)update(id << 1, pos, v);
        else update(id << 1 | 1, pos, v);
        c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
        c[id].maxm = max(c[id << 1].maxm, c[id << 1 | 1].maxm);
        c[id].minm = min(c[id << 1].minm, c[id << 1 | 1].minm);
    }
}
 
ll query_max(int id, int l, int r) {
    if (c[id].left == l && c[id].right == r)return c[id].maxm;
    int mid = (c[id].left + c[id].right) >> 1;
    if (c[id].add)pushdown(id);
    if (r <= mid)return query_max(id << 1, l, r);
    else if (l > mid)return query_max(id << 1 | 1, l, r);
    else return max(query_max(id << 1, l, mid), query_max(id << 1 | 1, mid + 1, r));
}
 
ll query_min(int id, int l, int r) {
    if (c[id].left == l && c[id].right == r)return c[id].minm;
    int mid = (c[id].left + c[id].right) >> 1;
    if (c[id].add)pushdown(id);
    if (r <= mid)return query_min(id << 1, l, r);
    else if (l > mid)return query_min(id << 1 | 1, l, r);
    else return min(query_min(id << 1, l, mid), query_min(id << 1 | 1, mid + 1, r));
}
 
void update(int id, int l, int r, ll v) {
    if (c[id].left > r || c[id].right < l)return;
    if (c[id].left >= l && c[id].right <= r) {
        c[id].add += v;
        c[id].sum += (c[id].right - c[id].left + 1) * v;
        return;
    }
    if (c[id].add)pushdown(id);
    update(id << 1, l, r, v);
    update(id << 1 | 1, l, r, v);
    c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
}
 
ll query_sum(int id, int l, int r) {
    if (r < c[id].left || l > c[id].right)return 0;
    if (c[id].left >= l && c[id].right <= r) {
        return c[id].sum;
    }
    if (c[id].add)pushdown(id);
    ll ans = query_sum(id << 1, l, r) + query_sum(id << 1 | 1, l, r);
    c[id].sum = c[id << 1].sum + c[id << 1 | 1].sum;
    return ans;
}
 
4.2.2 動態開點線段樹
const int maxn = (1e6 + 10) * 51;
const int inf = 1e9 + 10;

int ls[maxn], rs[maxn], cnt;

struct tree {
    int left, right, mmin;
} c[maxn];

void build(int id, int l, int r) {
    c[id].left = l;
    c[id].right = r;
    c[id].mmin = inf;
    ls[id] = rs[id] = 0;
}

void update(int id, int pos, int v) {
    if (c[id].left == c[id].right)c[id].mmin = min(c[id].mmin, v);
    else {
        int mid = (c[id].left + c[id].right) >> 1;
        if (pos <= mid) {
            if (ls[id] == 0) {
                ls[id] = cnt;
                build(cnt, c[id].left, mid);
                ++cnt;
            }
            update(ls[id], pos, v);
            c[id].mmin = min(c[id].mmin, c[ls[id]].mmin);
        } else {
            if (rs[id] == 0) {
                rs[id] = cnt;
                build(cnt, mid + 1, c[id].right);
                ++cnt;
            }
            update(rs[id], pos, v);
            c[id].mmin = min(c[id].mmin, c[rs[id]].mmin);
        }
    }
}

bool query_min(int id, int l, int r, int ck) {
    if (c[id].left == l && c[id].right == r)return (ck >= c[id].mmin);
    if (c[id].mmin > ck)return 0;
    int mid = (c[id].left + c[id].right) >> 1;
    if (r <= mid) {
        if (ls[id] != 0)return query_min(ls[id], l, r, ck);
    } else if (l > mid) {
        if (rs[id] != 0)return query_min(rs[id], l, r, ck);
    } else {
        if (ls[id] != 0 && query_min(ls[id], l, mid, ck))return 1;
        else if (rs[id] != 0 && query_min(rs[id], mid + 1, r, ck))return 1;
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章