区间严格最大次大区修+区查

本文介绍了如何使用C++实现了一个结构化的数据结构ST,包含节点定义、构建、更新和查询操作,重点展示了区间更新和查询的懒惰传播算法。通过随机化测试展示了其在处理区间问题中的应用。
摘要由CSDN通过智能技术生成
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
#define inf 0x3f3f3f3f
#define inff 1e18
#define pii pair<int, int>
#define pil pair<int, ll>
#define pll pair<ll, ll>
#define vi vector<int>
#define vl vector<ll>
#define fi first
#define se second

struct node{ll l, r, f, s, add;}; //f最大值; s次大值, 不存在为-inff; add懒标记
struct ST {
    static const ll N = 1e5 + 5;
    node tr[N * 4];
    void pushdown(node &t, node &l, node &r){
        if(t.add){
            l.f += t.add;
            r.f += t.add;
            if(l.s != -inff)
                l.s += t.add;
            if(r.s != -inff)
                r.s += t.add;
            l.add += t.add;
            r.add += t.add;
            t.add = 0;
        }
    }
    void pushup(node &t, node l, node r){
        t.f = max(l.f, r.f);
        ll s = -inff;
        if(l.f != t.f)
            s = max(s, l.f);
        if(l.s != t.f)
            s = max(s, l.s);
        if(r.f != t.f)
            s = max(s, r.f);
        if(r.s != t.f)
            s = max(s, r.s);
        t.s = s;
    }
    void build(ll o, ll l, ll r, vl &a){
        tr[o] = {l, r, a[l], -(ll)inff};
        if(l == r){
            return;
        }
        ll m = (l + r) >> 1;
        build(o << 1, l, m, a);
        build(o << 1 | 1, m + 1, r, a);
        pushup(tr[o], tr[o << 1], tr[o << 1 | 1]);
    }
    void upd(ll o, ll L, ll R, ll v){ //区修
        ll l = tr[o].l, r = tr[o].r;
        if(L <= l && r <= R){
            tr[o].f += v;
            if(tr[o].s != -inff)
                tr[o].s += v;
            tr[o].add += v;
            return;
        }
        ll m = (l + r) >> 1;
        pushdown(tr[o], tr[o << 1], tr[o << 1 | 1]);
        if(L <= m)
            upd(o << 1, L, R, v);
        if(R > m)
            upd(o << 1 | 1, L, R, v);
        pushup(tr[o], tr[o << 1], tr[o << 1 | 1]);
    }
    node query(ll o, ll L, ll R){
        ll l = tr[o].l, r = tr[o].r;
        if(L <= l && R >= r)
            return tr[o];
        ll li = o << 1, ri = o << 1 | 1;
        ll m = (l + r) >> 1;
        pushdown(tr[o], tr[o << 1], tr[o << 1 | 1]);
        if(R <= m)
            return query(li, L, R);
        else if(L > m)
            return query(ri, L, R);
        node t; //临时节点返回
        pushup(t, query(li, L, m), query(ri, m + 1, R));
        return t;
    }
}st;

int main() {
    //随机化数据测试
    srand(time(0));
    ll n = 100;
    vl a(n + 1);
    srand(time(0));
    for(int i = 1; i <= n; i++){
        a[i] = 0;
    }
    st.build(1, 1, n, a);
    for(int i = 1; i <= n; i++){
        for(int j = i; j <= n; j++){
            ll x = rand() % 10000;
            for(int k = i; k <= j; k++)
                a[k] += x;
            st.upd(1, i, j, x);
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = i + 1; j <= n; j++){
            priority_queue<ll, vl> q;
            for(int k = i; k <= j; k++){
                q.push(a[k]);
            }
            ll mx = q.top();
            while(q.size() && q.top() == mx)
                q.pop();
            ll r1 = !q.size() ? -(ll)inff : q.top();
            ll r2 = st.query(1, i, j).s;
            cout << r1 << " " << r2 << endl;
            if(r1 != r2)
                cout << "不一致!!!!!!!" << endl;
        }
    }
    return 0;
}

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值