线段树维护最值
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 - 线段树区间最值操作