线段树维护最值

Posted zfdyf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树维护最值相关的知识,希望对你有一定的参考价值。

hdu5306 : http://acm.hdu.edu.cn/showproblem.php?pid=5306

终于A了,暴力版线段树

重要思想就是维护最值的时候另外维护一个次值,当修改值介于次值和最值的时候,可以直接修改最值,而无需向下更新

#include <algorithm>
#include <iostream>
#include <iterator>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <cmath>
#include <cctype>
#include <cstdio>
#include <cstring>
using namespace std;
#define sd(x) scanf("%d",&(x))
#define sld(x) scanf("%ld",&(x))
#define slld(x) scanf("%lld",&(x))
#define sf(x) scanf("%f",&(x))
#define slf(x) scanf("%lf",&(x))
#define ss(x) scanf("%s",(x))
#define lson(x) ((x)<<1)
#define rson(x) ((x)<<1|1)
typedef long long ll;
typedef unsigned long long ull;
typedef long double real;
typedef pair<int, int> pll;
const real PI = acos(-1);

const int maxn = 1e6 + 100;
struct Node {
    ll mav, mavsum, miv;
    /*最大值, 最大值数量,次大值*/
    ll sum;
    /*子树求和*/
}arr[maxn <<2];
ll ql, qr, qval;

void pushup(int x) {
    int l = lson(x);
    int r = rson(x);
    arr[x].mav = max(arr[l].mav, arr[r].mav);
    arr[x].sum = arr[l].sum + arr[r].sum;
    arr[x].miv = max(arr[l].miv, arr[r].miv);
    if (arr[l].mav == arr[r].mav) {
        arr[x].mavsum = arr[l].mavsum + arr[r].mavsum;
    }
    else {
        arr[x].miv = max(arr[x].miv, min(arr[l].mav, arr[r].mav));
        arr[x].mavsum = arr[l].mav > arr[r].mav ? arr[l].mavsum : arr[r].mavsum;
    }
}

void down_tag(int x, int tag) {
    if (tag >= arr[x].mav) return;
    arr[x].sum -= arr[x].mavsum * (arr[x].mav - tag);
    arr[x].mav = tag;
}

void pushdown(int x) {
    down_tag(lson(x), arr[x].mav);
    down_tag(rson(x), arr[x].mav);
}

void build(int x, int l, int r) {
    if (l == r) {
        slld(arr[x].sum);
        arr[x].mav = arr[x].sum;
        arr[x].miv = -1;
        arr[x].mavsum = 1;
        return;
    }
    int mid = ((r - l) >>1) + l;
    if (l <= mid) build(lson(x), l, mid);
    if (r > mid) build(rson(x), mid + 1, r);
    pushup(x);
}

void modify(int x, int l, int r) {
    if (arr[x].mav <= qval) return;
    if (ql <= l && qr >= r && arr[x].miv < qval) {
        down_tag(x, qval);
        return;
    }
    pushdown(x);
    int mid = ((r - l) >>1) + l;
    if (ql <= mid) modify(lson(x), l, mid);
    if (qr > mid) modify(rson(x), mid + 1, r);
    pushup(x);
}

ll query_max(int x, int l, int r) {
    if (ql <= l && qr >= r) {
        return arr[x].mav;
    }
    pushdown(x);
    ll ans = 0;
    int mid = ((r - l) >>1) + l;
    if (ql <= mid) ans = query_max(lson(x), l, mid);
    if (qr > mid) ans = max(query_max(rson(x), mid + 1, r), ans);
    return ans;
}

ll query_sum(int x, int l, int r) {
    if (ql <= l && qr >= r) {
        return arr[x].sum;
    }
    ll ans = 0;
    pushdown(x);
    int mid = ((r - l) >>1) + l;
    if (ql <= mid) ans += query_sum(lson(x), l, mid);
    if (qr > mid) ans += query_sum(rson(x), mid + 1, r);
    return ans;
}

int main() {
    ll n, q, t;
    slld(t);
    while (t--){
        slld(n); slld(q);
        build(1, 1, n);
        while (q--) {
            ll op, l, r, val;
            scanf("%lld%lld%lld", &op, &ql, &qr);
            if (op == 0) {
                scanf("%lld", &qval);
                modify(1, 1, n);
            } else if (op == 1) {
                printf("%lld\n", query_max(1, 1, n));
            } else {
                printf("%lld\n", query_sum(1, 1, n));
            }
        }
    }
    return 0;
}

 

以上是关于线段树维护最值的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces - 1263E(线段树维护前缀和最值)

最敏捷的机器人(线段树维护区间最值)

[HDU5306] Gorgeous Sequence - 线段树区间最值操作

bzoj3064Tyvj 1518 CPU监控 线段树维护历史最值

模板动态最值

BZOJ.3064.CPU监控(线段树 历史最值)