线段树模板

单点修改

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr);
#define rep(i, x, y) for(int i=(x), _=(y);i<=_;i++)
#define rrep(i, x, y) for(int i=(x), _=(y);i>=_;i--)
#define all(x) x.begin(),x.end()
#define PII pair<int, int>
#define x first
#define y second
#define ll long long
#define int long long
#define endl '\n'
const int inf = LONG_LONG_MAX;
using i64 = long long;

const int N = 1e6;
#define lc p << 1
#define rc p << 1 | 1
struct Tree {
    int l, r, mx;
}tr[N * 4];

void pushup(int p) {
    tr[p].mx = max(tr[lc].mx, tr[rc].mx);
}
void build(int p, int l, int r) {
    tr[p] = {l, r, 0ll};
    if (l == r) return ;
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    pushup(p);
}

int query(int p, int ql, int qr) {
    if (ql <= tr[p].l && qr >= tr[p].r) return tr[p].mx;
    if (ql > tr[p].r || qr < tr[p].l) return 0;
    return max(query(lc, ql, qr), query(rc, ql, qr)); 
}

void modify(int p, int x, int k) {
    if (tr[p].l == tr[p].r && tr[p].l == x) {
        tr[p].mx = k;
        return ;
    }
    if (x <= tr[lc].r) modify(lc, x, k);
    if (x >= tr[rc].l) modify(rc, x, k);
    pushup(p);
}

int dp[N];
void solve() {
    int n, d; cin >> n >> d;
    build(1, 0ll, 500000ll);
    for (int i = 1; i <= n; i++) {
        int x; cin >> x;
        int l = max(0ll, x - d), r = min(500000ll, x + d);
        int t = query(1, l, r);
        dp[x] = t + 1;
        modify(1, x, dp[x]);
    }

    int ans = 0;
    for (int i = 1; i <= 5e5; i++) {
        ans = max(ans, dp[i]);
    }
    cout << ans << '\n';
}

signed main() {
    IOS;
    // int T; cin >> T;
    // while (T--)
        solve();
 
    return 0;
}

区间修改

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr);
#define rep(i, x, y) for(int i=(x), _=(y);i<=_;i++)
#define rrep(i, x, y) for(int i=(x), _=(y);i>=_;i--)
#define all(x) x.begin(),x.end()
#define PII pair<int, int>
#define x first
#define y second
#define ll long long
#define int long long
#define endl '\n'
const int inf = LONG_LONG_MAX;
using i64 = long long;

const int N = 4e5 + 10;
#define lc p << 1
#define rc p << 1 | 1
struct Tree {
    int l, r, sum, add, mul;
}tr[N * 4];

int n, q, mod;
int a[N];
void pushup(int p) {
    tr[p].sum = (tr[lc].sum + tr[rc].sum) % mod;
}

void build(int p, int l, int r) {
    tr[p] = {l, r, 0, 0, 1};
    if (l == r) {
        tr[p].sum = a[l] % mod;
        return ;
    }

    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    pushup(p);
}

void pushdown(int p) {
    tr[lc].sum = (tr[lc].sum * tr[p].mul % mod + (tr[p].add * (tr[lc].r - tr[lc].l + 1) % mod)) % mod;
    tr[lc].mul = (tr[lc].mul * tr[p].mul) % mod;
    tr[lc].add = (tr[lc].add * tr[p].mul + tr[p].add) % mod;

    tr[rc].sum = (tr[rc].sum * tr[p].mul % mod + (tr[p].add * (tr[rc].r - tr[rc].l + 1) % mod)) % mod;
    tr[rc].mul = (tr[rc].mul * tr[p].mul) % mod;
    tr[rc].add = (tr[rc].add * tr[p].mul + tr[p].add) % mod;

    tr[p].add = 0;
    tr[p].mul = 1;
}
void update_add(int p, int ql, int qr, int k) {
    if (tr[p].l > qr || tr[p].r < ql) return ;
    if (ql <= tr[p].l && qr >= tr[p].r) {
        tr[p].add = (tr[p].add + k) % mod;
        tr[p].sum = (tr[p].sum + (tr[p].r - tr[p].l + 1) * k) % mod;
        return ;
    }
    
    pushdown(p);
    int mid = tr[p].l + tr[p].r >> 1;
    if (ql <= mid) update_add(lc, ql, qr, k);
    if (qr > mid) update_add(rc, ql, qr, k);
    pushup(p);
}

void update_mul(int p, int ql, int qr, int k) {
    if (tr[p].l > qr || tr[p].r < ql) return ;
    if (ql <= tr[p].l && qr >= tr[p].r) {
        tr[p].mul = tr[p].mul * k % mod;
        tr[p].add = tr[p].add * k % mod;
        tr[p].sum = tr[p].sum * k % mod;
        return ;
    }

    pushdown(p);
    int mid = tr[p].l + tr[p].r >> 1;
    if (ql <= mid) update_mul(lc, ql, qr, k);
    if (qr > mid) update_mul(rc, ql, qr, k);
    pushup(p);
}

int query(int p, int ql, int qr) {
    if (tr[p].l > qr || tr[p].r < ql) return 0;
    if (ql <= tr[p].l && qr >= tr[p].r) return tr[p].sum % mod;
    pushdown(p);

    int ans = 0;
    int mid = tr[p].l + tr[p].r >> 1;
    if (ql <= mid) ans += query(lc, ql, qr);
    if (qr > mid) ans += query(rc, ql, qr);
    ans %= mod;
    return ans;
}

void solve() {
    cin >> n >> q >> mod;
    for (int i = 1; i <= n; i++) cin >> a[i];
    build(1, 1, n);

    while (q--) {
        int op; cin >> op;
        int l, r; cin >> l >> r;
        if (op == 1) {
            int k; cin >> k;
            update_mul(1, l, r, k);
        }
        else if (op == 2) {
            int k; cin >> k;
            update_add(1, l, r, k);
        }
        else {
            cout << query(1, l, r) << '\n';
        }
    }
}

signed main() {
    IOS;
    // int T; cin >> T;
    // while (T--)
        solve();
 
    return 0;
}

势能线段树

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr);
#define rep(i, x, y) for(int i=(x), _=(y);i<=_;i++)
#define rrep(i, x, y) for(int i=(x), _=(y);i>=_;i--)
#define all(x) x.begin(),x.end()
#define PII pair<int, int>
#define x first
#define y second
#define ll long long
//#define int long long
#define endl '\n'
const int inf = LONG_LONG_MAX;
using i64 = long long;

const int N = 4e5 + 10;
#define lc p << 1
#define rc p << 1 | 1

struct Tree {
    int l, r, sum, mx;
}tr[N * 4];
int a[N];

void pushup(int p) {
    tr[p].sum = tr[lc].sum | tr[rc].sum;
    tr[p].mx = max(tr[lc].mx, tr[rc].mx);
}

void build(int p, int l, int r) {
    tr[p] = {l, r, a[l], a[l]};
    if (l == r) return ;
    
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
    pushup(p);
}


void modify(int p, int x, int v) {
    if (x < tr[p].l || x > tr[p].r) return ;
    if (tr[p].l == tr[p].r && tr[p].l == x) {
        tr[p].sum = v;
        tr[p].mx = v;
        return ;
    }

    int mid = tr[p].l + tr[p].r >> 1;
    if (x <= mid) modify(lc, x, v);
    if (x > mid) modify(rc, x, v);
    pushup(p);
}

void update(int p, int ql, int qr, int v) {
    if (tr[p].l > qr || tr[p].r < ql) return ;
    if (tr[p].l == tr[p].r) {
        tr[p].sum &= v;
        tr[p].mx &= v;
        return ;
    }

    if ((tr[p].sum & v) == tr[p].sum) return ;
    update(lc, ql, qr, v);
    update(rc, ql, qr, v);
    pushup(p);
}

int query(int p, int ql, int qr) {
    if (tr[p].l > qr || tr[p].r < ql) return 0;
    if (ql <= tr[p].l && qr >= tr[p].r) return tr[p].mx;
    int ans = 0;
    int mid = tr[p].l + tr[p].r >> 1;
    if (ql <= mid) ans = max(ans, query(lc, ql, qr));
    if (qr > mid) ans = max(ans, query(rc, ql, qr));
    return ans;
}

int read() {
    int x; scanf("%lld", &x);
    return x;
}

char op[4];
void solve() {
    int n, m; n = read(), m = read();
    for (int i = 1; i <= n; i++) a[i] = read();
    build(1, 1, n);

    while (m--) {
        scanf("%s", op);
        if (op[0] == 'A') {
            int l, r, v; l = read(), r = read(), v = read();
            update(1, l, r, v);
        }
        else if (op[0] == 'U') {
            int x, v; x = read(), v = read();
            modify(1, x, v);
        }
        else {
            int l, r; l = read(), r = read();
            cout << query(1, l, r) << '\n';
        }
    }
}

signed main() {
    //IOS;
    // int T; cin >> T;
    // while (T--)
        solve();
 
    return 0;
}

主席树

区间第k大

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(nullptr);
#define rep(i, x, y) for(int i=(x), _=(y);i<=_;i++)
#define rrep(i, x, y) for(int i=(x), _=(y);i>=_;i--)
#define all(x) x.begin(),x.end()
#define PII pair<int, int>
#define x first
#define y second
#define ll long long
#define int long long
#define endl '\n'
const int inf = LONG_LONG_MAX;
using i64 = long long;

const int N = 2e5 + 10;
#define lc(x) tr[x].ch[0]
#define rc(x) tr[x].ch[1]
struct Tree {
    int ch[2];
    int s;
}tr[N * 22];
int root[N];
int a[N];
int idx;

void build(int &p, int l, int r) {
    p = ++idx;
    if (l == r) return ;
    int mid = l + r >> 1;
    build(lc(p), l, mid);
    build(rc(p), mid + 1, r);
}

void insert(int x, int &y, int l, int r, int v) {
    y = ++idx;
    tr[y] = tr[x];
    tr[y].s++;
    if (l == r) return ;
    int mid = l + r >> 1;
    if (v <= mid) insert(lc(x), lc(y), l, mid, v);
    else insert(rc(x), rc(y), mid + 1, r, v);
}

int query(int x, int y, int l, int r, int k) {
    if (l == r) return l;
    int mid = l + r >> 1;
    int sum = tr[lc(y)].s - tr[lc(x)].s;
    if (sum >= k) return query(lc(x), lc(y), l, mid, k);
    else return query(rc(x), rc(y), mid + 1, r, k - sum);
}

int arr[N];
void solve() {
    int n, m; cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        arr[i] = a[i];
    }  
    build(root[0], 1, n);

    sort(arr + 1, arr + 1 + n);
    for (int i = 1; i <= n; i++) {
        a[i] = lower_bound(arr + 1, arr + 1 + n, a[i]) - arr;
    }

    for (int i = 1; i <= n; i++) {
        insert(root[i - 1], root[i], 1, n, a[i]);
    }

    while (m--) {
        int l, r, k; cin >> l >> r >> k;
        int t = query(root[l - 1], root[r], 1, n, k);
        cout << arr[t] << '\n';
    }
}

signed main() {
    IOS;
    // int T; cin >> T;
    // while (T--)
        solve();
 
    return 0;
}

主席树二分

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
#define ull unsigned long long
#define all(x) x.begin(), x.end()
#define pb push_back
#define PII pair<int, int>
#define x first
#define y second
#define endl '\n'

inline int read() {int c; cin >> c; return c;}
inline void readn(int a[], int n) {
    for_each(a + 1, a + n + 1, [](int &x) {cin >> x;});
}
inline void writen(int a[], int n) {
    for_each(a + 1, a + n + 1, [](int &x) { cout << x << ' '; });
    cout << endl;
}
template<typename T, typename... Args>
void write(const T &first, const Args &...args) {
    cout << first;
    ((cout << ' ' << args), ...);
    cout << endl;
}
template<typename T, typename... Args>
void ewrite(const T& first, const Args&... args) {
    cerr << '*';
    cerr << first;
    ((cerr << ' ' << args), ...);
    cerr << endl;
}
char out[2][10] = {"No", "Yes"};
const double eps = 1e-6;
const int N = 1e6 + 10;
const int M = N << 1;
const int mod = 998244353;

/* next is main_solve */
int n;
int a[N];


struct node {
    int l, r, sum;
} o[N * 30];
int rt[N];
int tot;
int add(int x, int l, int r, int v) {
    int t = ++tot;
    o[t] = o[x];
    o[t].sum++;
    if (l == r)
        return t;
    int mid = (l + r) / 2;
    if (v <= mid)
        o[t].l = add(o[t].l, l, mid, v);
    else
        o[t].r = add(o[t].r, mid + 1, r, v);
    return t;
}

int asksum(int x, int l, int r, int ql, int qr)
{
    if (x == 0)
        return 0;
    if (ql <= l && r <= qr)
        return o[x].sum;
    int mid = l + r >> 1;
    if (ql <= mid && qr > mid)
        return asksum(o[x].l, l, mid, ql, qr) + asksum(o[x].r, mid + 1, r, ql, qr);
    else if (ql <= mid)
        return asksum(o[x].l, l, mid, ql, qr);
    else
        return asksum(o[x].r, mid + 1, r, ql, qr);
}
int ask(int x, int l, int r, int cnt)
{
    if (l == r)
        return l;
    int mid = l + r >> 1;
    if (o[o[x].l].sum >= cnt)
        return ask(o[x].l, l, mid, cnt);
    else
        return ask(o[x].r, mid + 1, r, cnt - o[o[x].l].sum);

}
int ask(int beg, int i, int k)
{

    int sum = o[rt[i]].sum; //总的大于等于i的位置的数量
    int suml;
    if (beg == 1)
        suml = 0;
    else
        suml = asksum(rt[i], 1, n, 1, beg - 1);//beg前面有几个大于等于i

    if (sum - suml < k) //如果剩下的数量不足k个则无法升级,返回n+1
        return n + 1;

    return ask(rt[i], 1, n, suml + k); //区间里第一个等于suml+k的位置
}

vector<int> sb[N];
vector<int> pos[N];

void solve() {
    n = read();
    int q;
    q = read();
    readn(a, n);

    for (int i = 1; i <= n; i++) {
        sb[a[i]].pb(i);
    }

    for (int i = 200000; i >= 1; i--) {
        rt[i] = rt[i + 1];
        for (auto x : sb[i]) {
            rt[i] = add(rt[i], 1, n, x);
        }
    }

    for (int k = 1; k <= n; k++) {
        for (int l = 1, r, i = 1; l <= n; i++) {
            r = ask(l, i, k);
            pos[k].pb(r);
            l = r + 1;
        }
    }

    while (q--) {
        int p, k;
        p = read(), k = read();
        int t = lower_bound(all(pos[k]), p) - pos[k].begin() + 1;
        if (a[p] >= t) {
            cout << "YES\n";
        }
        else {
            cout << "NO\n";
        }
    }
}

void cloud_fly() {
    // int t;
    // cin >> t;
    // while (t--)
    solve();
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cloud_fly();
    return 0;
}

扫描线

扫描线求面积

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1e5 + 10;

struct line{
    int x1, x2, y, tag;
}L[N * 2];
bool cmp(line l1, line l2) {
    return l1.y < l2.y;
}
int X[N * 2];

#define lc p << 1
#define rc p << 1 | 1
struct Tree{
    int l, r;
    int cnt, len;
}tr[N * 16];

void pushup(int p) {
    int l = tr[p].l, r = tr[p].r;
    if (tr[p].cnt > 0) tr[p].len = X[r + 1] - X[l];
    else tr[p].len = tr[lc].len + tr[rc].len;
}
void build(int p, int l, int r) {
    tr[p] = {l, r, 0, 0};
    if (l == r) return ;
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
}

void update(int p, int ql, int qr, int k) {
    if (tr[p].r < ql || tr[p].l > qr) return ;
    if (tr[p].l >= ql && tr[p].r <= qr) {
        tr[p].cnt += k;
        pushup(p);
        return ;
    }

    update(lc, ql, qr, k);
    update(rc, ql, qr, k);
    pushup(p);
}

void solve() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        L[i] = {x1, x2, y1, 1};
        L[n + i] = {x1, x2, y2, -1};
        X[i] = x1;
        X[n + i] = x2;
    }
    n *= 2;
    sort(L + 1, L + 1 + n, cmp);
    sort(X + 1, X + 1 + n);
    int m = unique(X + 1, X + 1 + n) - X - 1;
    build(1, 1, m - 1);

    int ans = 0;
    for (int i = 1; i < n; i++) {
        int ql = lower_bound(X + 1, X + 1 + m, L[i].x1) - X;
        int qr = lower_bound(X + 1, X + 1 + m, L[i].x2) - X;
        update(1, ql, qr - 1, L[i].tag);
        ans += 1ll * tr[1].len * (L[i + 1].y - L[i].y);
    }
    cout << ans << '\n';
}

signed main() {
    //freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0);

    // int T; cin >> T;
    // while (T--) 
        solve();

    return 0;
}

扫描线求周长

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 5e3 + 10;
int X[N * 2];
struct line{
    int x1, x2, y, tag;
    bool operator< (const line t) {
        if (y == t.y) return tag > t.tag;
        return y < t.y;
    }
}L[N * 16];

struct Tree{
    int l, r;
    int cnt, len; 
    int lcover, rcover, sum;
}tr[N * 8];
#define lc p << 1
#define rc p << 1 | 1

void build(int p, int l, int r) {
    tr[p] = {l, r, 0, 0, 0, 0, 0};
    if (l == r) return ;
    int mid = l + r >> 1;
    build(lc, l, mid);
    build(rc, mid + 1, r);
}

void pushup(int p) {
    int l = tr[p].l, r = tr[p].r;
    if (tr[p].cnt) {
        tr[p].len = X[r + 1] - X[l];
        tr[p].sum = 2;
        tr[p].lcover = tr[p].rcover = 1;
    }
    else {
        tr[p].len = tr[lc].len + tr[rc].len;
        tr[p].sum = tr[lc].sum + tr[rc].sum;
        tr[p].lcover = tr[lc].lcover;
        tr[p].rcover = tr[rc].rcover;
        if (tr[lc].rcover && tr[rc].lcover) {
            tr[p].sum -= 2;
        } 
    }
}

void update(int p, int ql, int qr, int k) {
    if (tr[p].r < ql || tr[p].l > qr) return ;
    if (tr[p].l >= ql && tr[p].r <= qr) {
        tr[p].cnt += k;
        pushup(p);
        return ;
    }
    update(lc, ql, qr, k);
    update(rc, ql, qr, k);
    pushup(p);
}

void solve() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        int x1, y1, x2, y2; cin >> x1 >> y1 >> x2 >> y2;
        X[i] = x1;
        X[n + i] = x2;
        L[i] = {x1, x2, y1, 1};
        L[n + i] = {x1, x2, y2, -1};
    }
    n *= 2;
    sort(X + 1, X + 1 + n);
    int m = unique(X + 1, X + 1 + n) - X - 1;
    sort(L + 1, L + 1 + n);

    build(1, 1, m - 1);
    int ans = 0;
    int lst = 0;
    for (int i = 1; i < n; i++) {
        int l = lower_bound(X + 1, X + 1 + m, L[i].x1) - X;
        int r = lower_bound(X + 1, X + 1 + m, L[i].x2) - X;
        update(1, l, r - 1, L[i].tag);
        ans += abs(tr[1].len - lst);
        lst = tr[1].len;
        ans += tr[1].sum * (L[i + 1].y - L[i].y);
    }
    ans += L[n].x2 - L[n].x1;
    cout << ans << '\n';
}

signed main() {
    //freopen("in.txt", "r", stdin);
    ios::sync_with_stdio(false), cin.tie(0);

    // int T; cin >> T;
    // while (T--) 
        solve();

    return 0;
}
相关推荐
m0_748234712 小时前
【大模型】Ollama+open-webuiAnything LLM部署本地大模型构建RAG个人知识库教程(Mac)
人工智能·macos
qq_207518514 小时前
MacBook Pro触控板按不动解决方法
经验分享·macos·电脑·笔记本电脑
嘟嘟实验室4 小时前
PDFMathTranslate,PDF多语言翻译,批量处理,学术论文,双语对照(WIN/MAC)
人工智能·macos·aigc·自动翻译
Magnetic_h5 小时前
【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数(三)
笔记·学习·ios·objective-c·cocoa
符小易5 小时前
Mac上安装illustrator 2025/2024总是提示130/131/已损坏等解决方法
macos·ui·illustrator
半夏知半秋8 小时前
unity打包流程整理-Windows/Mac/Linux平台
windows·笔记·学习·macos·unity·游戏引擎
牛奔8 小时前
解决 Mac(M1/M2)芯片,使用node 14版本
linux·macos·编辑器·vim
樱木之9 小时前
mac删除程序坞(Dock)中“无法打开的程序“
macos
丁总学Java10 小时前
Mac备忘录表格中换行(`Option` + `Return`(回车键))
macos
weixin_4978455412 小时前
.NET MAUI开发的安卓、iOS软件和Java开发的安卓和Swift开发的iOS的区别
macos·objective-c·cocoa