【知识】线段树!

线段树

P3372 【模板】线段树 1

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    const int N = 100005;
    struct node{
        int l, r;
        ll w, add;
    } tr[N << 2];
    ll a[N];
    int n, m;
    void pushup(int u){
        tr[u].w = tr[u << 1].w + tr[u << 1 | 1].w;
    }

    void pushdown(int u){
        if(tr[u].add){
            tr[u << 1].add += tr[u].add, tr[u << 1].w += (tr[u << 1].r - tr[u << 1].l + 1) * tr[u].add;
            tr[u << 1 | 1].add += tr[u].add, tr[u << 1 | 1].w += (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) * tr[u].add;
        }
        tr[u].add = 0;
    }
    void build(int u,int l,int r){
        tr[u].l = l, tr[u].r = r, tr[u].add = 0;
        if(l==r){
            tr[u].w = a[l];
            return;
        }
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }

    void update(int u,int l,int r,int k){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].add += k;
            tr[u].w += (tr[u].r - tr[u].l + 1) * k;
            return;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l<=mid)
            update(u << 1, l, r, k);
        if(r>mid)
            update(u << 1 | 1, l, r, k);
        pushup(u);
    }

    int query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r)
            return tr[u].w;
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1, res = 0;
        if(l<=mid)
            res += query(u << 1, l, r);
        if(r>mid)
            res += query(u << 1 | 1, l, r);
        return res;
    }

    void Main(){
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> a[i];

        build(1, 1, n);
        while(m--){
            int opt, x, y, k;
            cin >> opt >> x >> y;
            if(opt==1){
                cin >> k;
                update(1, x, y, k);
            }
            else{
                cout << query(1, x, y) << endl;
            }
        }
    }

}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    // T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P3373 【模板】线段树 2

多加了一个区间乘法,考虑多增加一个 mul 的懒标记,然后注意 pushdown 的时候要先算乘法后算加法,其他与模板一样

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    const int N = 100005;
    struct node{
        int l, r;
        int w, add, mul;
    } tr[N << 2];
    int a[N];
    int n, q, m;
    void pushup(int u){
        tr[u].w = tr[u << 1].w + tr[u << 1 | 1].w;
    } 

    void pushdown(int u){
        if(tr[u].mul!=1){
            tr[u << 1].mul *= tr[u].mul, tr[u << 1].add *= tr[u].mul, tr[u << 1].w *= tr[u].mul;
            tr[u << 1 | 1].mul *= tr[u].mul, tr[u << 1 | 1].add *= tr[u].mul, tr[u << 1 | 1].w *= tr[u].mul;
        }
        if(tr[u].add!=0){
            tr[u << 1].add += tr[u].add, tr[u << 1].w += (tr[u << 1].r - tr[u << 1].l + 1) * tr[u].add;
            tr[u << 1 | 1].add += tr[u].add, tr[u << 1 | 1].w += (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) * tr[u].add;
        }
        tr[u].mul = 1, tr[u].add = 0;
        tr[u << 1].w %= m, tr[u << 1].mul %= m, tr[u << 1].add %= m;
        tr[u << 1 | 1].w %= m, tr[u << 1 | 1].mul %= m, tr[u << 1 | 1].add %= m;
    }
    void build(int u,int l,int r){
        tr[u].l = l, tr[u].r = r, tr[u].add = 0, tr[u].mul = 1;
        if(l==r){
            tr[u].w = a[l];
            return;
        }
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }

    void update1(int u,int l,int r,int k){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].w = tr[u].w * k % m;
            tr[u].add = tr[u].add * k % m;
            tr[u].mul = tr[u].mul * k;
            return;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l<=mid)
            update1(u << 1, l, r, k);
        if(r>mid)
            update1(u << 1 | 1, l, r, k);
        pushup(u);
    }

    void update2(int u,int l,int r,int k){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].add = (tr[u].add + k) % m;
            tr[u].w = (tr[u].w + (tr[u].r - tr[u].l + 1) * k) % m;
            return;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l<=mid)
            update2(u << 1, l, r, k);
        if(r>mid)
            update2(u << 1 | 1, l, r, k);
        pushup(u);
    }

    int query(int u,int l,int r){
        if(tr[u].l>=l&&tr[u].r<=r){
            return tr[u].w;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1, res = 0;
        if(l<=mid)
            res = (res + query(u << 1, l, r)) % m;
        if(r>mid)
            res = (res + query(u << 1 | 1, l, r)) % m;
        return res;
    }

    void Main(){
        cin >> n >> q >> m;
        for (int i = 1; i <= n;i++)
            cin >> a[i];
        build(1, 1, n);
        while(q--){
            int opt, x, y, k;
            cin >> opt >> x >> y;
            if(opt==1){
                cin >> k;
                update1(1, x, y, k);
            }
            else if(opt==2){
                cin >> k;
                update2(1, x, y, k);
            }
            else{
                cout << query(1,x, y) << endl;
            }
        }
    }
}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    // T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P1712 [NOI2016] 区间

首先 l,r 很大,离散化!

然后按照区间长度 len 从小到大排序,依次将每个区间加入,直到存在一个点的覆盖次数大于 m,然后移动左指针删除一个区间,维护答案即可。

如何判断一个点的覆盖次数呢?用线段树进行区间加,求根节点的max 即可。

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    const int N = 1000005;
    int v[N << 1], cnt;
    int n, m;
    struct node{
        int l, r, len;
    } f[N];
    struct Tree{
        int l, r;
        int w, add, mx, posx;
    }tr[N<<2];

    bool cmp(node a,node b){
        return a.len < b.len;
    }
    void build(int u,int l,int r){
        tr[u].l = l, tr[u].r = r, tr[u].posx = l;
        if(l==r)
            return;
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    }

    void pushup(int u){
        tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
    }
    void pushdown(int u){
        if(tr[u].add){
            tr[u << 1].add += tr[u].add, tr[u << 1].mx += tr[u].add;
            tr[u << 1 | 1].add += tr[u].add, tr[u << 1 | 1].mx += tr[u].add;
        }
        tr[u].add = 0;
    }

    void update(int u,int l,int r,int k){
        if(tr[u].l>=l&&tr[u].r<=r){
            tr[u].mx += k;
            tr[u].add += k;
            return;
        }
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l<=mid)
            update(u << 1, l, r, k);
        if(r>mid)
            update(u << 1 | 1, l, r, k);
        pushup(u);
    }

    void Main(){
        cin >> n >> m;
        for (int i = 1; i <= n;i++){
            cin >> f[i].l >> f[i].r;
            f[i].len = f[i].r - f[i].l;
            v[++cnt] = f[i].l, v[++cnt] = f[i].r;
        }
        sort(v + 1, v + cnt + 1);
        int x = unique(v + 1, v + cnt + 1) - v - 1;
        for (int i = 1; i <= n;i++){
            f[i].l = lower_bound(v + 1, v + x + 1, f[i].l) - v;
            f[i].r = lower_bound(v + 1, v + x + 1, f[i].r) - v;
        }
        sort(f + 1, f + n + 1, cmp);
        build(1, 1, x);
        int fr = 1, ans = 0x3f3f3f3f;
        for (int i = 1; i <= n;i++){
            update(1, f[i].l, f[i].r, 1);
            while(tr[1].mx>=m){
                ans = min(ans, f[i].len - f[fr].len);
                update(1, f[fr].l, f[fr].r, -1);
                fr++;
            }
        }
        if(ans==0x3f3f3f3f)
            cout << -1 << endl;
        else
            cout << ans << endl;
    }

}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    // T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P4145 上帝造题的七分钟 2 / 花神游历各国

观察到每个数不会被开平方多次,于是可以暴力修改,对于一个区间,如果最大值为 1 了,那么整个区间都是 1,就不需要修改

线段树维护区间 max 即可。

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    const int N = 4000010;
    struct Tree{
        int l, r, w, mx;
    } tr[N << 2];
    int a[N], n, m;
    void pushup(int u){
        tr[u].w = tr[u << 1].w + tr[u << 1 | 1].w;
        tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
    }
    void build(int u,int l,int r){
        tr[u].l = l, tr[u].r = r;
        if(l==r){
            tr[u].w = tr[u].mx = a[l];
            return;
        }
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }

    void update(int u,int l,int r){
        if(tr[u].l==tr[u].r){
            tr[u].w = sqrt(tr[u].w), tr[u].mx = tr[u].w;
            return;
        }
        int mid = tr[u].l + tr[u].r >> 1;
        if(l<=mid&&tr[u<<1].mx>1)
            update(u << 1, l, r);
        if(r>mid&&tr[u<<1|1].mx>1)
            update(u << 1 | 1, l, r);
        pushup(u);
    }

    int query(int u,int l,int r){
        //DEBUG(u), DEBUG(l), DEBUG(r);
        if(tr[u].l>=l&&tr[u].r<=r){
            return tr[u].w;
        }
        int mid = tr[u].l+tr[u].r >> 1, res = 0;
        if(l<=mid)
            res += query(u << 1, l, r);
        if(r>mid)
            res += query(u << 1 | 1, l, r);
        return res;
    }
    void Main(){
        cin >> n;
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        build(1, 1, n);
        cin >> m;
        for (int i = 1; i <= m;i++){
            int opt, x, y;
            cin >> opt >> x >> y;
            if(x>y)
                swap(x, y);
            if(opt==1) {
                cout << query(1, x, y) << endl;
            }
            else{
                update(1, x, y);
            }
        }
    }

}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    // T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P4513 小白逛公园

纯线段树,考虑每个区间,维护当前区间的最大子段和,最大前缀和,最大后缀和。

pushup 合并时分别考虑三种情况(左子树的最大子段和,右子树的最大子段和,左子树的最大后缀和 + 右子树的最大前缀和)即可。

#include <bits/stdc++.h>
using namespace std;
#define FOR(i, a, b) for (int i = (a); i <= (b); ++i)
#define ROF(i, a, b) for (int i = (a); i >= (b); --i)
#define DEBUG(x) cerr << #x << " = " << x << endl
#define ll long long
typedef pair <int, int> PII;
typedef unsigned int uint;
typedef unsigned long long ull;
#define i128 __int128
#define fi first
#define se second
mt19937 rnd(chrono::system_clock::now().time_since_epoch().count());
#define ClockA clock_t start, end; start = clock()
#define ClockB end = clock(); cerr << "time = " << double(end - start) / CLOCKS_PER_SEC << "s" << endl;
//#define int long long
inline int rd(){
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
        x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x * f;
}
#define rd rd()

void wt(int x){
    if (x < 0)
        putchar('-'), x = -x;
    if (x > 9)
        wt(x / 10);
    putchar(x % 10 + '0');
    return;
}
void wt(char x){
    putchar(x);
}
void wt(int x, char k){
    wt(x),putchar(k);
}

namespace Star_F{
    const int N = 500010;
    int n, m;
    int w[N];
    struct Node{
        int l, r;
        int sum, lmax, rmax, tmax;
    }tr[N * 4];


    void pushup(Node &u, Node &l, Node &r){
        u.sum = l.sum + r.sum;
        u.lmax = max(l.lmax, l.sum + r.lmax);
        u.rmax = max(r.rmax, r.sum + l.rmax);
        u.tmax = max(max(l.tmax, r.tmax), l.rmax + r.lmax);
    }

    void pushup(int u){
        pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
    }

    void build(int u, int l, int r){
        if (l == r) tr[u] = {l, r, w[r], w[r], w[r], w[r]};
        else{
            tr[u] = {l, r};
            int mid = l + r >> 1;
            build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
            pushup(u);
        }
    }

    void modify(int u, int x, int v){
        if (tr[u].l == x && tr[u].r == x) tr[u] = {x, x, v, v, v, v};
        else{
            int mid = tr[u].l + tr[u].r >> 1;
            if (x <= mid) modify(u << 1, x, v);
            else modify(u << 1 | 1, x, v);
            pushup(u);
        }
    }

    Node query(int u, int l, int r){
        if (tr[u].l >= l && tr[u].r <= r) return tr[u];
        else{
            int mid = tr[u].l + tr[u].r >> 1;
            if (r <= mid) return query(u << 1, l, r);
            else if (l > mid) return query(u << 1 | 1, l, r);
            else{
                auto left = query(u << 1, l, r);
                auto right = query(u << 1 | 1, l, r);
                Node res;
                pushup(res, left, right);
                return res;
            }
        }
    }
    void Main(){
        cin >> n >> m;
        for (int i = 1; i <= n; i++)
            cin >> w[i];
        build(1, 1, n);
        int k, x, y;
        while (m--){
            cin >> k >> x >> y;
            if (k == 1){
                if (x > y) swap(x, y);
                printf("%d\n", query(1, x, y).tmax);
            }
            else modify(1, x, y);
        }
    }

}

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ClockA;
    int T=1;
    // T=rd;
    while(T--) Star_F::Main();
    // ClockB;
    return 0;
}


/*
*          ▀▀▀██████▄▄▄       _______________
*          ▄▄▄▄▄  █████████▄  /                 \
*         ▀▀▀▀█████▌ ▀▐▄ ▀▐█ | Code has no BUG!  |
*      ▀▀█████▄▄ ▀██████▄██ | _________________/
*       ▀▄▄▄▄▄  ▀▀█▄▀█════█▀ |/
*            ▀▀▀▄  ▀▀███ ▀       ▄▄
*         ▄███▀▀██▄████████▄ ▄▀▀▀▀▀▀█▌   ______________________________
*       ██▀▄▄▄██▀▄███▀ ▀▀████      ▄██  █                               \\
*    ▄▀▀▀▄██▄▀▀▌████▒▒▒▒▒▒███     ▌▄▄▀▀▀▀█_____________________________ //
*    ▌    ▐▀████▐███▒▒▒▒▒▐██▌
*    ▀▄▄▄▄▀   ▀▀████▒▒▒▒▄██▀
*              ▀▀█████████▀
*            ▄▄██▀██████▀█
*          ▄██▀     ▀▀▀  █
*         ▄█             ▐▌
*     ▄▄▄▄█▌              ▀█▄▄▄▄▀▀▄
*    ▌     ▐                ▀▀▄▄▄▀
*     ▀▀▄▄▀     ██
* \  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
* \- ▌           Name: Star_F              ▀ ▀
*  - ▌                            (o)          ▀
* /- ▌            Go Go Go !               ▀ ▀
* /  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▀
*/

P1486 [NOI2004] 郁闷的出纳员

我会 Splay

其实就是值域线段树,把每个员工的工资当作节点编号,节点的值当作出现次数,然后区间修改即可。

由于是全体工资加 k 或 减 k ,维护一个全局 add 即可。

因为编号都是大于 0的,再加上一个偏移量!

#include<bits/stdc++.h>
using namespace std;
const int M = 200005;
const int N = 500005;
struct Tree{
	int l,r;
	int sum,rem;
}t[N<<2];
int n,lim,D,now,ans;

void pushdown(int p){
	if(t[p].rem){
        t[p << 1].sum = t[p << 1 | 1].sum = 0;
        t[p << 1].rem = t[p << 1 | 1].rem = 1;
        t[p].rem = 0;
    }
}
void pushup(int p) { 
    t[p].sum = t[p << 1].sum + t[p << 1 | 1].sum; 
}

void build(int p,int l,int r){
    t[p].l = l, t[p].r = r;
    if(l==r){t[p].sum=0;
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    pushup(p);
} 
void change(int p,int x,int val){
	if(t[p].l==t[p].r){
        t[p].sum += val;
        return;
    }
	pushdown(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if(x<=mid)
        change(p << 1, x, val);
    else
        change(p << 1 | 1, x, val);
    pushup(p);
}
int query(int p,int k){
	if(t[p].l==t[p].r)
        return t[p].l;
    pushdown(p);
    if(t[p<<1].sum>=k)
        return query(p << 1, k);
    else
        return query(p << 1 | 1, k - t[p << 1].sum);
}
void upd(int p,int l,int r){
	if(l<=t[p].l&&t[p].r<=r){
		if(t[p].sum)
            now -= t[p].sum, ans += t[p].sum;
        t[p].sum = 0, t[p].rem = 1;
        return;
    }
	pushdown(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if(l<=mid)
        upd(p << 1, l, r);
    if(r>mid)
        upd(p << 1 | 1, l, r);
    pushup(p);
}
int main(){
    cin >> n >> lim;
    char op;
    build(1,1,N);
    for (int i = 1; i <= n; ++i){
        int k;
        cin >> op >> k;
        if(op=='I'){
			if(k>=lim)
                change(1, k - D + M, 1), now++;
        }
		else if(op=='A')
            D += k;
        else if(op=='S')
            D -= k, upd(1, 1, lim - D - 1 + M);
        else if(op=='F'){
			if(k>now) puts("-1");
			else cout << query(1, now - k + 1) + D - M << endl;
        }
    }
    cout << ans << endl;
    return 0;
}

P2824 [HEOI2016/TJOI2016] 排序

很神秘的一道题,调了好久。

考虑对于每个区间排序是很复杂的事情,但如果一个区间只有 01 那么排序便可以变成区间修改问题,及前一部分为 0 ,后一部分为 1

我们可以二分答案,假设当前答案为 mid ,给所有大于等于 mid 的修改成 1,小于 mid 的为 0,然后对于每个操作,统计多少个 1,多少个 0,进行区间覆盖即可完成排序,如果要求的点 q 的值为 1,则 l=mid+1,否则 r=mid-1

于是便可得出,线段树维护 区间和,tag(被覆盖成 tag )就可以了

复杂度 O(m×log2n)

#include <bits/stdc++.h>
using namespace std;
const int N = 400005;
struct Tree{
    int l, r;
    int w, tag;
} tr[N << 2];
int a[N];
void pushup(int u){
    tr[u].w = tr[u << 1].w + tr[u << 1 | 1].w;
}
void build(int u, int l, int r) {
    tr[u].l=l,tr[u].r=r,tr[u].tag = -1;
	if (l == r) {
		tr[u].w = a[l];
		return;
	}
	int mid = l + r >> 1;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
    pushup(u);
}
void pushdown(int u, int l, int r, int mid) {
	if (tr[u].tag == -1) return;
    tr[u << 1].tag = tr[u << 1 | 1].tag = tr[u].tag;
    tr[u << 1].w = tr[u].tag * (mid - l + 1);
    tr[u << 1 | 1].w = tr[u].tag * (r - mid);
    tr[u].tag = -1;
}
void cov(int u, int l,int r,int v) {
    if (l <= tr[u].l && tr[u].r <= r) {
		tr[u].tag = v;
		tr[u].w = v * (tr[u].r - tr[u].l + 1);
		return;
	}
	int mid = tr[u].l+tr[u].r >> 1;
	pushdown(u, tr[u].l, tr[u].r, mid);
	if (l <= mid)
		cov(u << 1, l, r, v);
	if (r > mid)
		cov(u << 1 | 1,l, r, v);
    pushup(u);
}
int ask(int u, int l, int r) {
    //cout<<u<<" "<<l<<" "<<r<<endl; 
	if (l<=tr[u].l && tr[u].r<=r)
        return tr[u].w;
    int mid = tr[u].l+tr[u].r>> 1, ans = 0;
	pushdown(u, tr[u].l, tr[u].r, mid);
	if (l <= mid)
		ans += ask(u << 1, l, r);
	if (r > mid)
		ans += ask(u << 1 | 1,l, r);
	return ans;
}
int b[N], n;
int opt[N], l[N], r[N], m, q;
bool solve(int x) {
	for (int i = 1; i <= n; i++) {
		if (b[i] >= x) a[i] = 1;
		else a[i] = 0;
	}
	build(1, 1, n);
	for (int i = 1; i <= m; i++) {
		if (opt[i] == 1) {
			int num = ask(1,l[i], r[i]);
			cov(1, l[i], l[i] + num - 1, 1);
			cov(1, l[i] + num, r[i], 0);
		} else {
			int num = ask(1, l[i], r[i]);
			cov(1, r[i] - num + 1, r[i], 1);
			cov(1, l[i], r[i] - num, 0);
		}
	}
	
	return ask(1, q, q);
}
int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> b[i];
	for (int i = 1; i <= m; i++) {
		cin >> opt[i] >> l[i] >> r[i];
	}
	cin >> q;
	int l = 1, r = n, ans = 0;
	while (l <= r) {
		int mid = l + r >> 1;
		if (solve(mid))
			ans = mid, l = mid + 1;
		else
			r = mid - 1;
	}
    cout << ans+1 << endl;
}
posted @   Star_F  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 【.NET】调用本地 Deepseek 模型
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
点击右上角即可分享
微信分享提示