[NOIP 考前备战] 线段树刷题

备战线段树

T1 AcWing .1275. 最大数

查询最大值 + 单点修改

#include <bits/stdc++.h>

#define int long long

using namespace std;

const int N = 1e7 + 5;

struct SegmentTree
{
    int l, r;
    int id;
} t[N * 4];

void push_up(int u)
{
    t[u].id = max(t[u << 1].id, t[u << 1 | 1].id);
}

void build(int p, int l, int r)
{
    t[p].l = l;
    t[p].r = r;
    if (l == r)
    {
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

int query(int p, int l, int r)
{
    if (t[p].l >= l && t[p].r <= r)
    {
        return t[p].id;
    }
    int mid = (t[p].l + t[p].r) >> 1;
    int v = 0;
    if (l <= mid)
    {
        v = query(p << 1, l, r);
    }
    if (r > mid)
    {
        v = max(v, query(p << 1 | 1, l, r));
    }
    return v;
}

void change(int p, int x, int v)
{
    if (t[p].l == t[p].r)
    {
        t[p].id = v;
        return;
    }
    int mid = (t[p].l + t[p].r) >> 1;
    if (x <= mid)
    {
        change(p << 1, x, v);
    }
    else
    {
        change(p << 1 | 1, x, v);
    }
    push_up(p);
}

int m, p;

signed main()
{
    cin >> m >> p;
    int n = 0;
    int last = 0;
    build(1, 1, m);

    while (m--)
    {
        char op;
        cin >> op;
        if (op == 'Q')
        {
            int x;
            cin >> x;
            last = query(1, n - x + 1, n);
            cout << last << endl;
        }
        else
        {
            int x;
            cin >> x;
            change(1, n + 1, (last + x) % p);
            n++;
        }
    }

    return 0;
}

T2 AcWing .245.你能回答这些问题吗

最大连续子段和 + 单点修改

#include <bits/stdc++.h>

#define rint register int
#define endl '\n'

using namespace std;

const int N = 2e6 + 5;
const int inf = 1e9;

struct SegmentTree
{
    int l, r;
    int lmax, rmax, sum, id;
} t[N];

int n, m, a[N];

void push_up(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
    t[u].lmax = max(t[u << 1].lmax, t[u << 1].sum + t[u << 1 | 1].lmax);
    t[u].rmax = max(t[u << 1 | 1].rmax, t[u << 1 | 1].sum + t[u << 1].rmax);
    t[u].id = max(max(t[u << 1].id, t[u << 1 | 1].id), t[u << 1].rmax + t[u << 1 | 1].lmax);
}

void build(int p, int l, int r)
{
    t[p].l = l;
    t[p].r = r;
    if (t[p].l == t[p].r)
    {
        t[p].id = t[p].sum = t[p].lmax = t[p].rmax = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

void change(int p, int x, int v)
{
    if (t[p].l == t[p].r)
    {
        t[p].id = v;
        t[p].sum = v;
        t[p].rmax = v;
        t[p].lmax = v;
        return ;
    }
    int mid = (t[p].l + t[p].r) >> 1;
    if (x <= mid)
    {
        change(p << 1, x, v);
    }
    else
    {
        change(p << 1 | 1, x, v);
    }
    push_up(p);
}

SegmentTree ask(int p, int l, int r)
{
    if (l <= t[p].l && r >= t[p].r)
    {
        return t[p];
    }
    int mid = (t[p].l + t[p].r) >> 1;
    SegmentTree a, b, c;
    a.id = a.lmax = a.rmax = a.sum = -inf;
    b.id = b.lmax = b.rmax = b.sum = -inf;

    c.sum = 0;

    if (l <= mid)
    {
        a = ask(p << 1, l, r);
        c.sum += a.sum;
    }
    if (r > mid)
    {
        b = ask(p << 1 | 1, l, r);
        c.sum += b.sum;
    }
    c.id = max(max(a.id, b.id), a.rmax + b.lmax);
    c.lmax = max(a.lmax, b.lmax + a.sum);
    if (l > mid)
    {
        c.lmax = max(c.lmax, b.lmax);
    }
    c.rmax = max(b.rmax, b.sum + a.rmax);
    if (r <= mid)
    {
        c.rmax = max(c.rmax, a.rmax);
    }
    return c;
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    build(1, 1, n);
    while (m--)
    {
        int op, x, y;
        cin >> op >> x >> y;
        if (op == 1)
        {
            if (x > y)
            {
                swap(x, y);
            }
            cout << ask(1, x, y).id << endl;
        }
        if (op == 2)
        {
            change(1, x, y);
        }
    }

    return 0;
}

T3 AcWing.246.区间最大公约数

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 5e6 + 5;

int n, m,w[N];

struct SegmentTree
{
    int l, r;
    int sum, id; //id存储最大公约数
} t[N];

void push_up(SegmentTree &u, SegmentTree &l, SegmentTree &r)
{
    u.sum = l.sum + r.sum;
    u.id = __gcd(l.id, r.id);
}

void push_up(int u)
{
    push_up(t[u], t[u << 1], t[u << 1 | 1]);
}

void build(int p, int l, int r)
{
    if (l == r)
    {
        int b = w[r] - w[r - 1];
        t[p] = {l, r, b, b};
    }
    else
    {
        t[p].l = l;
        t[p].r = r;
        int mid = (l + r) >> 1;
        build(p << 1, l, mid);
        build(p << 1 | 1, mid + 1, r);
        push_up(p);
    }
}

void change(int p, int x, int v)
{
    if (t[p].l == x && t[p].r == x)
    {
        int b = t[p].sum + v;
        t[p] = {x, x, b, b};
    }
    else
    {
        int mid = (t[p].l + t[p].r) >> 1;
        if (x <= mid)
        {
            change(p << 1, x, v);
        }
        else
        {
            change(p << 1 | 1, x, v);
        }
        push_up(p);
    }
}

SegmentTree query(int p, int l, int r)
{
    if (t[p].l >= l && t[p].r <= r)
    {
        return t[p];
    }
    else
    {
        int mid = (t[p].l + t[p].r) >> 1;
        if (r <= mid)
        {
            return query(p << 1, l, r);
        }
        else if (l > mid)
        {
            return query(p << 1 | 1, l, r);
        }
        else
        {
            auto left = query(p << 1, l, r);
            auto right = query(p << 1 | 1, l, r);
			SegmentTree res;
			push_up(res, left, right);
            return res;
        }
    }
}

signed main()
{
    cin >> n >> m;
    for (rint i = 1; i <= n; i++)
    {
        cin >> w[i];
    }
    build(1, 1, n);
    int l, r;
    int d;
    char op;
    while (m--)
    {
        cin >> op >> l >> r;
        if (op == 'Q')
        {
            auto left = query(1, 1, l);
            SegmentTree right({0, 0, 0, 0});
            if (l + 1 <= r)
            {
                right = query(1, l + 1, r);
            }
            cout << abs(__gcd(left.sum, right.id)) << endl;
        }
        else
        {
            cin >> d;
            change(1, l, d);
            if (r + 1 <= n)
            {
                change(1, r + 1, -d);
            }
        }
    }

    return 0;
}

T4 P2023 [AHOI2009]维护序列

区间修改 + 询问区间和

#include <bits/stdc++.h>

#define int long long
#define rint register int
#define endl '\n'

using namespace std;

const int N = 1e6 + 5;

int n, m, mod, w[N];

struct SegmentTree
{
    int l, r;
    int add, sum, mul;
} t[N << 2];

void push_up(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
    t[u].sum = t[u].sum % mod;
}

void push_down(int u)
{
    t[u << 1].sum = (t[u << 1].sum * t[u].mul + t[u].add * (t[u << 1].r - t[u << 1].l + 1)) % mod;
    t[u<<1|1].sum = (t[u<<1|1].sum * t[u].mul + t[u].add * (t[u<<1|1].r-t[u<<1|1].l+1)) % mod;
    t[u << 1].add = (t[u << 1].add * t[u].mul + t[u].add) % mod;
    t[u << 1 | 1].add = (t[u << 1 | 1].add * t[u].mul + t[u].add) % mod;
    t[u << 1].mul = t[u << 1].mul * t[u].mul % mod;
    t[u << 1 | 1].mul = t[u << 1 | 1].mul * t[u].mul % mod;
    t[u].add = 0;
    t[u].mul = 1;
}

void build(int p, int l, int r)
{
    if (l == r)
    {
        t[p] = {l, r, 0, w[r], 1};
        return;
    }
    t[p] = {l, r, 0, 0, 1};
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

void change(int p, int l, int r, int mul, int add)
{
    if (t[p].l >= l && t[p].r <= r)
    {
        t[p].sum = (t[p].sum * mul + add * (t[p].r - t[p].l + 1)) % mod;
        t[p].add = (t[p].add * mul + add) % mod;
        t[p].mul = t[p].mul * mul % mod;
        return;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if (l <= mid)
    {
        change(p << 1, l, r, mul, add);
    }
    if (r > mid)
    {
        change(p << 1 | 1, l, r, mul, add);
    }
    push_up(p);
}

int query(int p, int l, int r)
{
    if (t[p].l >= l && t[p].r <= r)
    {
        return t[p].sum;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    int res = 0;
    if (l <= mid)
    {
        res += query(p << 1, l, r);
        res = res % mod;
    }
    if (r > mid)
    {
        res += query(p << 1 | 1, l, r);
        res = res % mod;
    }
    return res;
}

signed main()
{
    cin >> n >> mod;
    for (rint i = 1; i <= n; i++)
    {
        cin >> w[i];
    }
    build(1, 1, n);
    cin >> m;
    while (m--)
    {
        int op, l, r, c;
        cin >> op >> l >> r;
        if (op == 1)
        {
            cin >> c;
            change(1, l, r, c, 0); //*c+0
        }
        if (op == 2)
        {
            cin >> c;
            change(1, l, r, 1, c); //*1+c
        }
        if (op == 3)
        {
            cout << query(1, l, r) << endl;
        }
    }

    return 0;
}

T5 P6242 【模板】线段树 3

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 1e7 + 5;
const int inf = 2e9;

int n, m, op, l, r, k;

struct SegmentTree
{
    int sum;
    int l, r, maxx, cnt, cmax, hmax;
    // maxx  该区间的最大值
    // cnt   该区间最大值的个数
    // cmax  该区间的次大值
    // hmax  该区间的历史最大值
    int add1, add2, add3, add4;
    // add1   该区间最大值的懒标。
    // add2   该区间非最大值的懒标记
    // add3   该区间最大值的懒标记的最大值
    // add4   该区间非最大的值的懒标记的最大值
} t[N];

inline int read()
{
    int x = 0, falg = 0;
    char c = getchar();
    while (c > '9' || c < '0')
    {
        if (c == '-')
            falg = 1;
        c = getchar();
    }
    while (c <= '9' && c >= '0')
    {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return falg ? -x : x;
}

void push_up(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
    t[u].maxx = max(t[u << 1].maxx, t[u << 1 | 1].maxx);
    t[u].hmax = max(t[u << 1].hmax, t[u << 1 | 1].hmax);
    
    if (t[u << 1].maxx == t[u << 1 | 1].maxx)
    {
        t[u].cmax = max(t[u << 1].cmax, t[u << 1 | 1].cmax);
        t[u].cnt = t[u << 1].cnt + t[u << 1 | 1].cnt;
    }
    
    else if (t[u << 1].maxx > t[u << 1 | 1].maxx)
    {
        t[u].cmax = max(t[u << 1].cmax, t[u << 1 | 1].maxx);
        t[u].cnt = t[u << 1].cnt;
    }
    
    else
    {
        t[u].cmax = max(t[u << 1].maxx, t[u << 1 | 1].cmax);
        t[u].cnt = t[u << 1 | 1].cnt;
    }
}

void build(int p, int l, int r)
{
    t[p].l = l;
    t[p].r = r;
    if (l == r)
    {
        t[p].sum = t[p].maxx = t[p].hmax = read();
        t[p].cnt = 1;
        t[p].cmax = -inf;
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

void change(int p, int k1, int k2, int k3, int k4)
{
    // k1    区间最大值要加的数
    // k2    区间非最大值要加的的数
    // k3    区间最大值要加上的数的最大值
    // k4    区间非最大值要加上的数的最大值
    t[p].sum += k1 * t[p].cnt + k2 * (t[p].r - t[p].l + 1 - t[p].cnt);
    t[p].hmax = max(t[p].hmax, t[p].maxx + k3);
    t[p].add3 = max(t[p].add3, t[p].add1 + k3);
    t[p].add4 = max(t[p].add4, t[p].add2 + k4);
    t[p].maxx += k1;
    t[p].add1 += k1;
    t[p].add2 += k2;
    if (t[p].cmax != -inf)
    {
        t[p].cmax += k2;
    }
}

void push_down(int u)
{
    int maxn = max(t[u << 1].maxx, t[u << 1 | 1].maxx);

    if (t[u << 1].maxx == maxn)
    {
        change(u << 1, t[u].add1, t[u].add2, t[u].add3, t[u].add4);
    }
    else
    {
        change(u << 1, t[u].add2, t[u].add2, t[u].add4, t[u].add4);
    }

    if (t[u << 1 | 1].maxx == maxn)
    {
        change(u << 1 | 1, t[u].add1, t[u].add2, t[u].add3, t[u].add4);
    }
    else
    {
        change(u << 1 | 1, t[u].add2, t[u].add2, t[u].add4, t[u].add4);
    }

    t[u].add1 = t[u].add2 = t[u].add3 = t[u].add4 = 0;
}

void update_add(int p, int l, int r, int k)
{
    if (l > t[p].r || t[p].l > r)
    {
        return;
    }
    if (l <= t[p].l && t[p].r <= r)
    {
        change(p, k, k, k, k);
        return;
    }
    push_down(p);
    update_add(p << 1, l, r, k);
    update_add(p << 1 | 1, l, r, k);
    push_up(p);
}

void update_min(int p, int l, int r, int k)
{
    if (l > t[p].r || t[p].l > r || k >= t[p].maxx)
    {
        return;
    }
    if (l <= t[p].l && t[p].r <= r && k > t[p].cmax)
    {
        change(p, k - t[p].maxx, 0, k - t[p].maxx, 0);
        return;
    }
    push_down(p);
    update_min(p << 1, l, r, k);
    update_min(p << 1 | 1, l, r, k);
    push_up(p);
}

int query_sum(int p, int l, int r)
{
    if (l > t[p].r || t[p].l > r)
    {
        return 0;
    }
    if (l <= t[p].l && t[p].r <= r)
    {
        return t[p].sum;
    }
    push_down(p);
    return query_sum(p << 1, l, r) + query_sum(p << 1 | 1, l, r);
}

int query_maxx(int p, int l, int r)
{
    if (l > t[p].r || t[p].l > r)
    {
        return -inf;
    }
    if (l <= t[p].l && t[p].r <= r)
    {
        return t[p].maxx;
    }
    push_down(p);
    return max(query_maxx(p << 1, l, r), query_maxx(p << 1 | 1, l, r));
}

int query_hmax(int p, int l, int r)
{
    if (l > t[p].r || t[p].l > r)
    {
        return -inf;
    }
    if (l <= t[p].l && t[p].r <= r)
    {
        return t[p].hmax;
    }
    push_down(p);
    return max(query_hmax(p << 1, l, r), query_hmax(p << 1 | 1, l, r));
}

signed main()
{
    n = read();
    m = read();
    build(1, 1, n);
    while (m--)
    {
        op = read();
        l = read();
        r = read();

        if (op == 1)
        {
            k = read();
            update_add(1, l, r, k);
        }

        if (op == 2)
        {
            k = read();
            update_min(1, l, r, k);
        }

        if (op == 3)
        {
            cout << query_sum(1, l, r) << endl;
        }

        if (op == 4)
        {
            cout << query_maxx(1, l, r) << endl;
        }

        if (op == 5)
        {
            cout << query_hmax(1, l, r) << endl;
        }
    }

    return 0;
}

T6 P4145 花神游历各国

区间开方 + 区间查询

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 4e5 + 5;

struct SegmentTree
{
    int sum;
    bool tag; //表示这个节点对应的区间内的数是否都是 0 或 1。
    //一个点如果是1或者0,那么这个点的开根是没有意义的
    //而即使是一个1e9,在经过不到10次开根后也会变成1
    //要是这个点是1或者0,那么tag就等于1
    //在维护的时候,只要左右子节点的tag都等于1时,这个点的tag就等于1
} t[N];

int w[N], n, m;

void push_up(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
    if (t[u << 1].tag && t[u << 1 | 1].tag)
    {
        t[u].tag = 1;
    }
    else
    {
        t[u].tag = 0;
    }
}

void build(int u, int l, int r)
{
    if (l == r)
    {
        t[u].sum = w[l];
        if (w[l] == 0 || w[l] == 1)
        {
            t[u].tag = 1;
        }
        else
        {
            t[u].tag = 0;
        }
        return;
    }
    int mid = (l + r) >> 1;
    build(u << 1, l, mid);
    build(u << 1 | 1, mid + 1, r);
    push_up(u);
}

void change(int u, int l, int r, int x, int v)
{
    if (l == r)
    {
        t[u].sum = sqrt(t[u].sum);
        if (t[u].sum == 0 || t[u].sum == 1)
        {
            t[u].tag = 1;
        }
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid && !t[u << 1].tag)
    {
        change(u << 1, l, mid, x, v);
    }
    if (v > mid && !t[u << 1 | 1].tag)
    {
        change(u << 1 | 1, mid + 1, r, x, v);
    }
    push_up(u);
}

int query(int u, int l, int r, int x, int v)
{
    if (x <= l && v >= r)
    {
        return t[u].sum;
    }
    int mid = (l + r) >> 1;
    int res = 0;
    if (x <= mid)
    {
        res += query(u << 1, l, mid, x, v);
    }
    if (v > mid)
    {
        res += query(u << 1 | 1, mid + 1, r, x, v);
    }
    return res;
}

inline int read()
{
    int x = 0;
    bool f = 0;
    char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-')
            f = 1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        x = (x << 3) + (x << 1) + c - 48;
        c = getchar();
    }
    return f ? -x : x;
}

signed main()
{
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    cin >> n; 
    for (rint i = 1; i <= n; i++)
    {
        w[i] = read();
    }
    build(1, 1, n);
    m = read();
    while (m--)
    {
        int op = read(), l = read(), r = read();
        if (l > r)
        {
            swap(l, r);
        }
        if (op == 0)
        {
            change(1, 1, n, l, r);
        }
        if (op == 1)
        {
            cout << query(1, 1, n, l, r) << endl;
        }
    }
    return 0;
}

T7 CF240F TorCoder

回文字符串问题 多棵线段树


#define rint register int
#define endl '\n'

using namespace std;

const int N = 1e5 + 5;

int n, q, ans[26 + 4];
char s[N];

struct SegmentTree
{
    int l, r;
    int sum[26 + 4];
    int add;
    // sum 为节点上每个字母的数量 add 为 lazy 标记
    //如果父区间存 2 个 a , lazy 即为 a , 需要时下放
} t[N << 2];

void clear(int u)
{
    for (rint i = 1; i <= 26; i++)
    {
        t[u].sum[i] = 0;
    }
}

void push_up(int u)
{
    for (rint i = 1; i <= 26; i++)
    {
        t[u].sum[i] = t[u << 1].sum[i] + t[u << 1 | 1].sum[i];
    }
}

void push_down(int u)
{
    if (t[u].add)
    {
        t[u << 1].add = t[u].add;
        t[u << 1 | 1].add = t[u].add;
        clear(u << 1);
        clear(u << 1 | 1);
        t[u << 1].sum[t[u].add] = t[u << 1].r - t[u << 1].l + 1;
        t[u << 1 | 1].sum[t[u].add] = t[u << 1 | 1].r - t[u << 1 | 1].l + 1;
        t[u].add = 0;
    }
}

void build(int p, int l, int r)
{
    t[p].l = l;
    t[p].r = r;
    if (l == r)
    {
        t[p].sum[s[l] - 'a' + 1] = 1;
        t[p].add = s[l] - 'a' + 1;
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

void query(int p, int l, int r)
{
    if (t[p].l == l && r == t[p].r)
    {
        for (int i = 1; i <= 26; i++)
        {
            ans[i] += t[p].sum[i];
        }
        return;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if (r <= mid)
    {
        query(p << 1, l, r);
    }
    else if (l > mid)
    {
        query(p << 1 | 1, l, r);
    }
    else
    {
        query(p << 1, l, mid);
        query(p << 1 | 1, mid + 1, r);
    }
    push_up(p);
}

void update(int p, int l, int r, int x)
{
    if (t[p].l == l && r == t[p].r)
    {
        clear(p);
        t[p].add = x;
        t[p].sum[x] = t[p].r - t[p].l + 1;
        return;
    }
    push_down(p);
    int mid = (t[p].l + t[p].r) >> 1;
    if (r <= mid)
    {
        update(p << 1, l, r, x);
    }
    else if (l > mid)
    {
        update(p << 1 | 1, l, r, x);
    }
    else
    {
        update(p << 1, l, mid, x);
        update(p << 1 | 1, mid + 1, r, x);
    }
    push_up(p);
}

void change(int l, int r)
{
    memset(ans, 0 ,sizeof ans);
    query(1, l, r);
    int sum = 0;
    for (rint i = 1; i <= 26; i++)
    {
        if (ans[i] & 1)
        {
        	sum++;
		}
        if (sum > 1)
        {
        	return ;
		}
    }
    for (rint i = 1; i <= 26; i++)
    {
        if (ans[i])
        {
            if (ans[i] / 2)
            {
                update(1, l, l + ans[i] / 2 - 1, i);
                update(1, r - ans[i] / 2 + 1, r, i);
                l += ans[i] / 2;
                r -= ans[i] / 2;
            }
            if (ans[i] % 2)
            {
                int mid = (l + r) >> 1;
                update(1, mid, mid, i);
            }
        }
    }
}

void query_print(int p, int l, int r)
{
    if (t[p].add)
    {
        for (int i = 1; i <= t[p].r - t[p].l + 1; i++)
        {
            putchar(t[p].add - 1 + 'a');
        }
        return;
    }
    int mid = (l + r) >> 1;
    query_print(p << 1, l, mid);
    query_print(p << 1 | 1, mid + 1, r);
}

int main()
{
    // freopen("input.txt", "r", stdin);
    // freopen("output.txt", "w", stdout);
    cin >> n >> q >> s + 1;
    build(1, 1, n);
    int l, r;
    
    while (q--)
    {
        int l ,r;
        cin >> l >> r;
        change(l, r);
    }
    
    query_print(1, 1, n);

    return 0;
}

T8 P3924 康娜的线段树

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 1e6 + 5;

int n, m, qwq;
int max_deep, res, ans;
int a[N], dep[N], sum[N];

struct SegmentTree
{
    int l, r;
    int sum, add;
} t[N << 2];

void push_up(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
}

void build(int p, int l, int r, int d)
{
    t[p].l = l;
    t[p].r = r;
    if (l == r)
    {
        t[p].sum = a[l];
        dep[l] = d;
        max_deep = max(max_deep, dep[l]);
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid, d + 1);
    build(p << 1 | 1, mid + 1, r, d + 1);
    push_up(p);
}

int query(int p, int l, int r, int d, int sum)
{
    if (l == r)
    {
        return (1 << d) * (sum + t[p].sum);
    }
    else
    {
        int mid = (l + r) >> 1;
        return query(p << 1, l, mid, d - 1, sum + t[p].sum) + query(p << 1 | 1, mid + 1, r, d - 1, sum + t[p].sum);
    }
}

signed main()
{
    ios::sync_with_stdio (false) ;
    cin.tie(0);
    cout.tie(0);
    
    cin >> n >> m >> qwq;
    
    for (rint i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    
    build(1, 1, n, 1);
    ans = query(1, 1, n, max_deep - 1, 0);
    res = 1 << (max_deep - 1);
    int g = __gcd(qwq, res);
    
    res /= g;
    qwq /= g;
    
    for (rint i = 1; i <= n; i++)
    {
        sum[i] = sum[i - 1] + (((1 << dep[i]) - 1) << (max_deep - dep[i]));
    }
    
    for (rint i = 1; i <= m; i++)
    {
        int l, r, x;
        cin >> l >> r >> x;
        ans += (sum[r] - sum[l - 1]) * x;
        cout << (ans / res * qwq) << endl;
    }

    return 0;
}

T9 CF444C DZY Loves Colors

#include <bits/stdc++.h>

#define rint register int
#define endl '\n'
#define int long long

using namespace std;

const int N = 1e5 + 5;

int n, m;

struct SegmentTree
{
    int lazy;
    int ans, len;
    int val;
} t[N << 2];

void push_up(int u)
{
    t[u].ans = t[u << 1].ans + t[u << 1 | 1].ans;
}

void push_down(int u, int l, int r)
{
    t[u << 1].lazy += t[u].lazy;
    t[u << 1 | 1].lazy += t[u].lazy;
    t[u << 1].ans += t[u].lazy * t[u << 1].len;
    t[u << 1 | 1].ans += t[u].lazy * t[u << 1 | 1].len;
    t[u << 1].val = t[u << 1 | 1].val = t[u].val;
    t[u].lazy = 0;
    t[u].val = 0;
}

void build(int p, int l, int r)
{
    t[p].len = r - l + 1;
    t[p].ans = t[p].lazy = t[p].val = 0;
    if (l == r)
    {
        t[p].val = l;
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
}

void change(int p, int l, int r, int L, int R, int x)
{
    if (L <= l && r <= R && t[p].val)
    {
        t[p].lazy += abs(t[p].val - x);
        t[p].ans += abs(t[p].val - x) * t[p].len;
        t[p].val = x;
        return;
    }
    if (t[p].val)
    {
        push_down(p, l, r);
    }
    int mid = (l + r) >> 1;
    if (L <= mid)
    {
        change(p << 1, l, mid, L, R, x);
    }
    if (R > mid)
    {
        change(p << 1 | 1, mid + 1, r, L, R, x);
    }
    t[p].val = t[p << 1].val == t[p << 1 | 1].val ? t[p << 1].val : 0;
    push_up(p);
}

int query(int p, int l, int r, int L, int R)
{
    if (L <= l && r <= R)
    {
        return t[p].ans;
    }
    if (t[p].val)
    {
        push_down(p, l, r);
    }
    int mid = (l + r) >> 1;
    int res = 0;
    if (L <= mid)
    {
        res += query(p << 1, l, mid, L, R);
    }
    if (R > mid)
    {
        res += query(p << 1 | 1, mid + 1, r, L, R);
    }

    return res;
}

signed main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
	
	cin >> n >> m;

    build(1, 1, n);

    while (m--)
    {
        int op, l, r, x;
        cin >> op;
        if (op == 1)
        {
            cin >> l >> r >> x;
            change(1, 1, n, l, r, x);
        }
        if (op == 2)
        {
            cin >> l >> r;
            cout << query(1, 1, n, l, r) << endl;
        }
    }

    return 0;
}

T10 CF1696D Permutation Graph

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int mod = 5;
const int N = 2e6 + 10;
const int inf = 0x3f3f3f3f;

int n, m, ans, l, r, a[N], pos[N];

struct SegmentTree
{
    int l, r;
    int minn, maxn;
} t[N];

void push_up(int u)
{
    t[u].minn = min(t[u << 1].minn, t[u << 1 | 1].minn);
    t[u].maxn = max(t[u << 1].maxn, t[u << 1 | 1].maxn);
}

void build(int p, int l, int r)
{
    t[p] = {l, r};
    
    if (l == r)
    {
        t[p] = {l, r, a[l], a[r]};
        return;
    }

    int mid = l + r >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

int query_max(int u, int l, int r)
{
    if (t[u].l >= l && t[u].r <= r)
    {
        return t[u].maxn;
    }
    int mid = (t[u].l + t[u].r) >> 1;
    int maxn = -inf;

    if (l <= mid)
    {
        maxn = max(maxn, query_max(u << 1, l, r));
    }
    if (r > mid)
    {
        maxn = max(maxn, query_max(u << 1 | 1, l, r));
    }

    push_up(u);

    return maxn;
}

int query_min(int u, int l, int r)
{
    if (t[u].l >= l && t[u].r <= r)
    {
        return t[u].minn;
    }

    int mid = (t[u].l + t[u].r) >> 1;
    int minn = inf;

    if (l <= mid)
    {
        minn = min(minn, query_min(u << 1, l, r));
    }
    if (r > mid)
    {
        minn = min(minn, query_min(u << 1 | 1, l, r));
    }

    push_up(u);

    return minn;
}

int dfs(int l, int r)
{
    if (l + 1 == r)
    {
        return 1;
    }
    if (l >= r)
    {
        return 0;
    }

    int maxn = query_max(1, l, r);
    int minn = query_min(1, l, r);

    int L = pos[maxn], R = pos[minn];

    if (L > R)
    {
        swap(L, R);
    }

    return dfs(l, L) + 1 + dfs(R, r);
}

signed main()
{
    int T;
	cin >> T;
    
    while(T--)
    {
        cin >> n;
        for (rint i = 1; i <= n; i++)
        {
            cin >> a[i]; 
			pos[a[i]] = i;        	
		}
        build(1, 1, n);
        if (n == 1)
        {
            cout << 0 << endl;
            continue;
        }
        cout << dfs(1, n) << endl;
    }
    
    return 0;
}

T11 P3602 Koishi Loves Segments

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 4e6 + 5;

struct SegmentTree
{
    int l, r;
    int minn, lazy;
} t[N];

bool cmp(SegmentTree x, SegmentTree y)
{
    if (x.r == y.r)
    {
        return x.l > y.l;
    }

    return x.r < y.r;
}

int stk1[N], top1, stk2[N], top2;
int s[N], num;
int a[N], n, m;

int inline max(int a, int b)
{
    return a > b ? a : b;
}

void push_up(int u)
{
    t[u].minn = min(t[u << 1].minn, t[u << 1 | 1].minn);
}

void build(int u, int l, int r)
{
    if (l == r)
    {
        t[u].minn = a[l];
        return;
    }

    int mid = l + r >> 1;

    build(u << 1, l, mid);
    build(u << 1 | 1, mid + 1, r);
    push_up(u);
}

void add(int u, int v)
{
    t[u].minn += v;
    t[u].lazy += v;
}

void pushdown(int u, int v)
{
    if (!t[u].lazy)
    {
        return;
    }

    add(u << 1, t[u].lazy);
    add(u << 1 | 1, t[u].lazy);
    t[u].lazy = 0;
}

int query(int u, int l, int r, int x, int y)
{
    if (l > y || r < x)
    {
        return 0x3f3f3f3f;   	
	}
    if (l >= x && r <= y)
    {
        return t[u].minn;    	
	}

    pushdown(u, t[u].lazy);
    
    int mid = l + r >> 1;
    int ans = 0x3f3f3f3f;
    
    if (x <= mid)
    {
        ans = min(ans, query(u << 1, l, mid, x, y));    	
	}
    if (y > mid)
    {
        ans = min(ans, query(u << 1 | 1, mid + 1, r, x, y));    	
	}

    return ans;
}

void change(int u, int l, int r, int x, int y, int v)
{
    if (l > y || r < x)
        return;
    if (l >= x && r <= y)
    {
        add(u, v);
        return;
    }

    pushdown(u, t[u].lazy);
    int mid = l + r >> 1;

    if (x <= mid)
    {
        change(u << 1, l, mid, x, y, v);
    }
    if (y > mid)
    {
        change(u << 1 | 1, mid + 1, r, x, y, v);
    }
    push_up(u);
}

signed main()
{
    cin >> n >> m;
    
    for (rint i = 1; i <= n; i++)
    {
        cin >> t[i].l >> t[i].r;
        s[++num] = t[i].l;
        s[++num] = t[i].r;
    }
    
    for (rint i = 1; i <= m; i++)
    {
        cin >> stk1[++top1] >> stk2[++top2];
        s[++num] = stk1[top1];
    }
    
    sort(s + 1, s + num + 1);
    int maxn = unique(s + 1, s + num + 1) - s - 1;

    for (rint i = 1; i <= n; i++)
    {
        t[i].l = lower_bound(s + 1, s + maxn + 1, t[i].l) - s;
        t[i].r = lower_bound(s + 1, s + maxn + 1, t[i].r) - s;
    }

    memset(a, 0x3f, sizeof a);

    for (rint i = 1; i <= m; i++)
    {
        int x = lower_bound(s + 1, s + maxn + 1, stk1[i]) - s;
        a[x] = min(a[x], max(stk2[i], 0));
    }

    sort(t + 1, t + n + 1, cmp);
    build(1, 1, maxn);
    int ans = 0;

    for (rint i = 1; i <= n; i++)
    {
        if (query(1, 1, maxn, t[i].l, t[i].r) > 0)
        {
            ans++;
            change(1, 1, maxn, t[i].l, t[i].r, -1);
        }
    }

    cout << ans << endl;

    return 0;
}

T12 P4513 小白逛公园

#include <bits/stdc++.h>

#define rint register int
#define int long long
#define endl '\n'

using namespace std;

const int N = 5e6 + 5;
const int inf = 0x3f3f3f3f;

int a[N], n, m;

struct SegmentTree
{
    int lx, sum, rx;
    int ans;
    int l, r;
    //lx    左边界以左的最大子段和
    //rx    右边界以右的最大子段和
    //ans   最后的最大子段和
    //sum   区间总和
} t[N];

void push_up(int u)
{
    t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
    t[u].lx = max(t[u << 1].lx, t[u << 1].sum + t[u << 1 | 1].lx);
    t[u].rx = max(t[u << 1 | 1].rx, t[u << 1 | 1].sum + t[u << 1].rx);
    t[u].ans = max(max(t[u << 1].ans, t[u << 1 | 1].ans), t[u << 1].rx + t[u << 1 | 1].lx);
}

void build(int p, int l, int r)
{
    t[p].l = l;
    t[p].r = r;
    if (l == r)
    {
        t[p].sum = t[p].lx = t[p].rx = t[p].ans = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(p << 1, l, mid);
    build(p << 1 | 1, mid + 1, r);
    push_up(p);
}

void change(int p, int l, int r, int x, int v)
{
    if (x < l || x > r)
    {
        return;
    }
    if (l == x && r == x)
    {
        t[p].ans = t[p].lx = t[p].rx = t[p].sum = v;
        return;
    }
    int mid = l + ((r - l) >> 1);
    change(p << 1, l, mid, x, v);
    change(p << 1 | 1, mid + 1, r, x, v);
    push_up(p);
}

SegmentTree query(int p, int l, int r)
{
    if (l <= t[p].l && r >= t[p].r)
    {
        return t[p];
    }
    SegmentTree a, b, ans;
    a.lx = a.rx = a.ans = -inf;
    b.lx = b.rx = b.ans = -inf;
    a.sum = b.sum = 0;
    ans.ans = -inf;
    ans.sum = 0;
    int mid = (t[p].l + t[p].r) >> 1;
    if (l <= mid)
    {
        a = query(p << 1, l, r);
        ans.sum += a.sum;
    }
    if (r >= mid + 1)
    {
        b = query(p << 1 | 1, l, r);
        ans.sum += b.sum;
    }
    ans.ans = max(a.rx + b.lx, max(a.ans, b.ans));
    ans.lx = max(a.lx, a.sum + b.lx);
    ans.rx = max(b.rx, b.sum + a.rx);
    if (l > mid)
    {
        ans.lx = max(ans.lx, b.lx);
    }
    if (r < mid)
    {
        ans.rx = max(ans.rx, a.rx);
    }
    return ans;
}

signed main()
{
    cin >> n >> m;
    for (rint i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    build(1, 1, n);
    while (m--)
    {
        int op, l, r;
        cin >> op >> l >> r;
        if (op == 1)
        {
            if (l > r)
            {
                swap(l, r);
            }
            cout << query(1, l, r).ans << endl;
        }
        if (op == 2)
        {
            change(1, 1, n, l, r);
        }
    }

    return 0;
}
posted @ 2022-08-13 21:18  PassName  阅读(33)  评论(0编辑  收藏  举报