Codeforces-EDU-SegmentTree-Part1

Codeforces-EDU-SegmentTree-Part1

step1
A.Segment Tree for the Sum
#include <iostream>
using namespace std;
using ll = long long;
const int N = 100010;
int a[N];
struct SegmentTreeForTheSum
{
    int l, r;
    ll sum;
} tr[N << 2];
void pushup(int u)
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].sum = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}
void modify(int u, int k, int x)
{
    if (tr[u].l == k && tr[u].r == k)
    {
        // a[u] = x;
        tr[u].sum = x;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k, x);
    else
        modify(u << 1 | 1, k, x);
    pushup(u);
}
ll query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)
        return tr[u].sum;
    int mid = tr[u].l + tr[u].r >> 1;
    ll rs = 0;
    if (l <= mid)
        rs = query(u << 1, l, r);
    if (r > mid)
        rs += query(u << 1 | 1, l, r);
    return rs;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int 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)
            a[l] = r, modify(1, l + 1, r);
        else
            cout << query(1, l + 1, r) << endl;
    }
    return 0;
}

B.Segment Tree for the Minimum
#include <iostream>
using namespace std;
using ll = long long;
const int N = 100010;
int a[N];
struct SegmentTreeForTheSum
{
    int l, r;
    ll minm;
} tr[N << 2];
void pushup(int u)
{
    tr[u].minm = min(tr[u << 1].minm, tr[u << 1 | 1].minm);
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].minm = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}
void modify(int u, int k, int x)
{
    if (tr[u].l == k && tr[u].r == k)
    {
        // a[u] = x;
        tr[u].minm = x;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k, x);
    else
        modify(u << 1 | 1, k, x);
    pushup(u);
}
ll query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)
        return tr[u].minm;
    int mid = tr[u].l + tr[u].r >> 1;
    ll rs = 0x3f3f3f3f;
    if (l <= mid)
        rs = query(u << 1, l, r);
    if (r > mid)
        rs = min(rs, query(u << 1 | 1, l, r));
    return rs;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int 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)
            a[l] = r, modify(1, l + 1, r);
        else
            cout << query(1, l + 1, r) << endl;
    }
    return 0;
}

C.Number of Minimums on a Segment
#include <iostream>
using namespace std;
using ll = long long;
const int N = 100010;
int a[N];
struct SegmentTreeForTheSum
{
    int l, r;
    ll minm, cnt;
} tr[N << 2];
void pushup(int u)
{
    tr[u].minm = min(tr[u << 1].minm, tr[u << 1 | 1].minm);
    if (tr[u << 1].minm == tr[u << 1 | 1].minm)
        tr[u].cnt = tr[u << 1].cnt + tr[u << 1 | 1].cnt;
    else if (tr[u << 1].minm < tr[u << 1 | 1].minm)
        tr[u].cnt = tr[u << 1].cnt;
    else
        tr[u].cnt = tr[u << 1 | 1].cnt;
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].minm = a[l];
        tr[u].cnt = 1;
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}
void modify(int u, int k, int x)
{
    if (tr[u].l == k && tr[u].r == k)
    {
        // a[u] = x;
        tr[u].minm = x;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k, x);
    else
        modify(u << 1 | 1, k, x);
    pushup(u);
}
pair<ll, ll> compare(pair<ll, ll> a, pair<ll, ll> b)
{
    if (a.first > b.first)
        return b;
    if (a.first < b.first)
        return a;
    return {a.first, a.second + b.second};
}
pair<ll, ll> query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r)
        return {tr[u].minm, tr[u].cnt};
    int mid = tr[u].l + tr[u].r >> 1;
    // ll rs = 0x3f3f3f3f, cnt = 0;
    pair<ll, ll> rs = {0x3f3f3f3f, 0};
    if (l <= mid)
    {
        rs = compare(rs, query(u << 1, l, r));
    }
    if (r > mid)
    {
        rs = compare(rs, query(u << 1 | 1, l, r));
    }
    return rs;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int 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)
            modify(1, l + 1, r);
        else
        {
            auto ans = query(1, l + 1, r);
            cout << ans.first << ' ' << ans.second << "\n";
        }
    }
    return 0;
}

Step2
A.Segment with the Maximum Sum
#include <iostream>
using namespace std;
using ll = long long;
const int N = 100010;
int a[N];
struct SegmentTreeForTheMaximumSubSegment
{
    int l, r;
    ll mx, mlx, mrx, sum; // 最大子段和,最大前缀和, 最大后缀和, 区间和
} tr[N << 2];
void pushup(int u)
{
    // 更新最大子段和
    tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
    tr[u].mx = max(tr[u].mx, tr[u << 1].mrx + tr[u << 1 | 1].mlx);

    // 更新最大前缀和
    tr[u].mlx = max(tr[u << 1].mlx, tr[u << 1].sum + tr[u << 1 | 1].mlx);

    // 更新最大后缀和
    tr[u].mrx = max(tr[u << 1 | 1].mrx, tr[u << 1 | 1].sum + tr[u << 1].mrx);

    // 更新区间和
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].mx = tr[u].mlx = tr[u].mrx = tr[u].sum = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}
void modify(int u, int k, int x)
{
    if (tr[u].l == k && tr[u].r == k)
    {
        tr[u].mx = tr[u].mlx = tr[u].mrx = tr[u].sum = x;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k, x);
    else
        modify(u << 1 | 1, k, x);
    pushup(u);
}
struct info
{
    ll mx, mlx, mrx, sum;
};
info compare(info a, info b)
{
    info rs;
    rs.mx = max(a.mx, max(b.mx, a.mrx + b.mlx));
    rs.mlx = max(a.mlx, a.sum + b.mlx);
    rs.mrx = max(b.mrx, b.sum + a.mrx);
    rs.sum = a.sum + b.sum;
    return rs;
}
info query(int u, int l, int r)
{
    info rs;
    if (tr[u].l >= l && tr[u].r <= r)
    {
        rs.mx = tr[u].mx;
        rs.mlx = tr[u].mlx;
        rs.mrx = tr[u].mrx;
        rs.sum = tr[u].sum;
        return rs;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (l <= mid)
    {
        rs = query(u << 1, l, r);
    }
    if (r > mid)
    {
        rs = compare(rs, query(u << 1 | 1, l, r));
    }

    return rs;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    build(1, 1, n);
    ll t = query(1, 1, n).mx;
    if (t > 0)
        cout << t << endl;
    else
        cout << 0 << endl;
    while (m--)
    {
        int op, l, r;
        cin >> l >> r;
        modify(1, l + 1, r);
        t = query(1, 1, n).mx;
        if (t > 0)
            cout << t << endl;
        else
            cout << 0 << endl;
    }
    return 0;
}

B.K-th one
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Node
{
    int l, r;
    int sum;
} tr[N << 2];
int a[N];
void pushup(int u)
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].sum = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}
void modify(int u, int k)
{
    if (tr[u].l == tr[u].r)
    {
        if (a[k] == 1)
        {
            a[k] = 0;
            tr[u].sum = 0;
        }
        else
        {
            a[k] = 1;
            tr[u].sum = 1;
        }
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
    {
        modify(u << 1, k);
    }
    else if (k > mid)
        modify(u << 1 | 1, k);
    pushup(u);
}
int query(int u, int k)
{
    if (tr[u].l == tr[u].r)
        return tr[u].r;
    int ml = tr[u << 1].sum, mr = tr[u << 1 | 1].sum;
    if (k < ml)
        return query(u << 1, k);
    else
    {
        return query(u << 1 | 1, k - ml);
    }
}
int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    build(1, 0, n - 1);
    while (m--)
    {
        int op, x;
        cin >> op;
        if (op == 1)
        {
            cin >> x;
            modify(1, x);
        }
        else
        {
            cin >> x;
            cout << query(1, x) << endl;
        }
    }
}
C.First element at least X
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Node
{
    int l, r, mx;
} tr[N << 2];
int a[N];
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].mx = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
}
void modify(int u, int k, int x)
{
    if (tr[u].l == tr[u].r)
    {
        tr[u].mx = x;
        a[k] = x;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k, x);
    if (k > mid)
        modify(u << 1 | 1, k, x);
    tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
}
int query(int u, int k)
{
    if (tr[u].mx < k)
        return -1;
    if (tr[u].l == tr[u].r)
        return tr[u].l;
    int ml = tr[u << 1].mx, mr = tr[u << 1 | 1].mx;
    if (k <= ml)
        return query(u << 1, k);
    else
        return query(u << 1 | 1, k);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    build(1, 1, n);
    while (m--)
    {
        int op, k, x;
        cin >> op;
        if (op == 1)
        {
            cin >> k >> x;
            k++;
            modify(1, k, x);
        }
        else
        {
            cin >> k;
            int rs = query(1, k);
            cout << (rs == -1 ? -1 : rs - 1) << endl;
        }
    }
}
D.First element at least X - 2
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
struct Node
{
    int l, r, mx;
} tr[N << 2];
int a[N];
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        tr[u].mx = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
}
void modify(int u, int k, int x)
{
    if (tr[u].l == tr[u].r)
    {
        tr[u].mx = x;
        a[k] = x;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k, x);
    if (k > mid)
        modify(u << 1 | 1, k, x);
    tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
}
int query(int u, int l, int k)
{
    if (tr[u].r < l)
        return -1;
    if (tr[u].mx < k)
        return -1;
    if (tr[u].l == tr[u].r)
        return tr[u].l;
    int ml = tr[u << 1].mx, mr = tr[u << 1 | 1].mx;
    int rs;
    rs = query(u << 1, l, k);
    if (rs < l)
        rs = query(u << 1 | 1, l, k);
    return rs;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    build(1, 1, n);
    while (m--)
    {
        int op, k, x;
        cin >> op;
        if (op == 1)
        {
            cin >> k >> x;
            k++;
            modify(1, k, x);
        }
        else
        {
            cin >> k >> x;
            x++;
            int rs = query(1, x, k);
            cout << (rs == -1 ? -1 : rs - 1) << '\n';
        }
    }
}
Step3
A. Inversions
#include <iostream>
using namespace std;
const int N = 100010;
int a[N], n;
struct Node
{
    int l, r, sum;
} tr[N << 2];
int st[N];
void build(int u, int l, int r)
{
    tr[u] = {l, r, 0};
    if (l == r)
        return;
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}
void modify(int u, int k)
{
    if (tr[u].l == tr[u].r)
    {
        tr[u].sum = 1;
        st[k] = 1;
        return;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    if (k <= mid)
        modify(u << 1, k);
    else
        modify(u << 1 | 1, k);
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
// return the sum of index [x + 1, n] values
int query(int u, int x)
{
    if (tr[u].l >= x + 1 && tr[u].r <= n)
        return tr[u].sum;
    int rs = 0;
    int mid = tr[u].l + tr[u].r >> 1;
    if (x + 1 <= mid)
        rs = query(u << 1, x);
    if (n > mid)
        rs += query(u << 1 | 1, x);
    return rs;
}
int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    build(1, 1, n);
    for (int i = 1; i <= n; i++)
    {
        cout << query(1, a[i]) << ' ';
        modify(1, a[i]);
    }
    return 0;
}

B.Inversions 2
#include <iostream>
#include <vector>
using namespace std;
const int N = 100010;
int a[N], n;
int f[N << 2];
void build(int u, int l, int r)
{
    if (l == r)
    {
        f[u] = 1;
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    f[u] = f[u << 1] + f[u << 1 | 1];
}
void modify(int u, int l, int r, int k)
{
    if (l == r && l == k)
    {
        f[u] = 0;
        return;
    }
    int mid = l + r >> 1;
    if (k <= mid)
        modify(u << 1, l, mid, k);
    else
        modify(u << 1 | 1, mid + 1, r, k);
    f[u] = f[u << 1] + f[u << 1 | 1];
}
// return the sum of index [x + 1, n] values
// find [sum, k] which matches the sum of index [k + 1, n] values that sum equals to x
int query(int u, int l, int r, int k)
{
    if (l == r)
        return l;
    int mid = l + r >> 1;
    int sum = f[u << 1 | 1];
    if (k < sum)
        return query(u << 1 | 1, mid + 1, r, k);
    else
        return query(u << 1, l, mid, k - sum);
}
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> a[i];
    build(1, 1, n);
    vector<int> v;
    for (int i = n - 1; i >= 0; i--)
    {
        int x = query(1, 1, n, a[i]);
        v.push_back(x);
        modify(1, 1, n, x);
    }
    for (int i = n - 1; i >= 0; i--)
        cout << v[i] << ' ';
    return 0;
}

C.Nested Segments
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;

int segtree[200010 << 2];
int n;
int a[200010];
int st[200010], ans[200010];
inline void update(int i, int l, int r, int x)
{
    if (l == r)
    {
        segtree[i] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
    {
        update(i << 1, l, mid, x);
    }
    else
    {
        update(i << 1 | 1, mid + 1, r, x);
    }
    segtree[i] = segtree[i << 1] + segtree[i << 1 | 1];
}
int calc(int i, int l, int r, int x)
{
    if (l == r)
    {
        return segtree[i];
    }
    int mid = (l + r) >> 1;
    if (x > mid)
    {
        return calc(i << 1 | 1, mid + 1, r, x);
    }
    return segtree[i << 1 | 1] + calc(i << 1, l, mid, x);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    n <<= 1;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (st[a[i]])
        {
            int sum = calc(1, 1, n, st[a[i]]);
            ans[a[i]] = sum;
            update(1, 1, n, st[a[i]]);
        }
        st[a[i]] = i + 1;
    }
    for (int i = 1; i <= n / 2; i++)
    {
        cout << ans[i] << " \n"[i == n / 2];
    }

    return 0;
}
D.Intersecting Segments
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;

int segtree[200010 << 2];
int n;
int a[200010];
int st[200010], ans[200010];
inline void update(int i, int l, int r, int x)
{
    if (l == r)
    {
        segtree[i] = 1;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
    {
        update(i << 1, l, mid, x);
    }
    else
    {
        update(i << 1 | 1, mid + 1, r, x);
    }
    segtree[i] = segtree[i << 1] + segtree[i << 1 | 1];
}
int calc(int i, int l, int r, int x)
{
    if (l == r)
    {
        return segtree[i];
    }
    int mid = (l + r) >> 1;
    if (x > mid)
    {
        return calc(i << 1 | 1, mid + 1, r, x);
    }
    return segtree[i << 1 | 1] + calc(i << 1, l, mid, x);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    n <<= 1;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (st[a[i]])
        {
            int sum = calc(1, 1, n, st[a[i]]);
            ans[a[i]] = i - st[a[i]] - sum * 2;
            update(1, 1, n, st[a[i]]);
        }
        st[a[i]] = i + 1;
    }
    for (int i = 1; i <= n / 2; i++)
    {
        cout << ans[i] << " \n"[i == n / 2];
    }

    return 0;
}
E. Addition to Segment
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll N = 100010;
struct Node
{
    ll l, r, add, sum;
} tr[N << 2];
void build(ll u, ll l, ll r)
{
    tr[u] = {l, r, 0, 0};
    if (l == r)
        return;
    ll mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
}
void pushup(ll u)
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void pushdown(ll u)
{
    if (tr[u].add)
    {
        tr[u << 1].add += tr[u].add;
        tr[u << 1 | 1].add += tr[u].add;
        tr[u << 1].sum += (tr[u << 1].r - tr[u << 1].l + 1) * tr[u].add;
        tr[u << 1 | 1].sum += (tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1) * tr[u].add;
        tr[u].add = 0;
    }
}
void modify(ll u, ll l, ll r, ll v)
{
    if (tr[u].l >= l && tr[u].r <= r)
    {
        tr[u].add += v;
        tr[u].sum += (tr[u].r - tr[u].l + 1) * v;
        return;
    }
    pushdown(u);
    ll mid = tr[u].l + tr[u].r >> 1;
    if (l <= mid)
        modify(u << 1, l, r, v);
    if (r > mid)
        modify(u << 1 | 1, l, r, v);
    pushup(u);
}
ll query(ll u, ll v)
{
    if (v < tr[u].l || v > tr[u].r)
        return 0;
    if (tr[u].l == tr[u].r && tr[u].l == v)
        return tr[u].sum;
    pushdown(u);
    ll mid = tr[u].l + tr[u].r >> 1;
    if (v <= mid)
        return query(u << 1, v);
    return query(u << 1 | 1, v);
}

int main()
{
    ll n, m;
    cin >> n >> m;
    n++;
    build(1, 1, n);
    while (m--)
    {
        ll op;
        cin >> op;
        if (op == 1)
        {
            ll l, r, v;
            cin >> l >> r >> v;
            l++;
            modify(1, l, r, v);
        }
        else
        {
            ll v;
            cin >> v;
            v++;
            cout << query(1, v) << endl;
        }
    }
}
Step4
A.Sign alternation
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int N = 100010;
i64 f[N << 2];
i64 a[N];
i64 n, m;
void build(int u, int l, int r)
{
    if (l == r)
    {
        f[u] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    f[u] = f[u << 1] + f[u << 1 | 1];
}
void update(int u, int l, int r, int x, int y)
{
    if (l == r)
    {
        f[u] = y;
        return;
    }
    int mid = (l + r) >> 1;
    if (x <= mid)
    {
        update(u << 1, l, mid, x, y);
    }
    else
    {
        update(u << 1 | 1, mid + 1, r, x, y);
    }
    f[u] = f[u << 1] + f[u << 1 | 1];
}
i64 query(int u, int l, int r, int x, int y)
{
    if (l == x && r == y)
    {
        return f[u];
    }
    int mid = (l + r) >> 1;
    if (y <= mid)
    {
        return query(u << 1, l, mid, x, y);
    }
    else
    {
        if (x > mid)
        {
            return query(u << 1 | 1, mid + 1, r, x, y);
        }
        else
        {
            return query(u << 1, l, mid, x, mid) + query(u << 1 | 1, mid + 1, r, mid + 1, y);
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (i & 1)
        {
            a[i] = -a[i];
        }
    }
    build(1, 1, n);
    cin >> m;
    while (m--)
    {
        int op;
        cin >> op;
        if (op == 0)
        {
            int x;
            i64 v;
            cin >> x >> v;
            if (x & 1)
            {
                v = -v;
            }
            update(1, 1, n, x, v);
        }
        else
        {
            int x, y;
            cin >> x >> y;
            i64 ans = query(1, 1, n, x, y);
            if (x & 1)
            {
                ans = -ans;
            }
            cout << ans << '\n';
        }
    }

    return 0;
}
B.Cryptography
#include <bits/stdc++.h>
using namespace std;
const int N = 200010;
int mod, n, m;
int a[N][2][2];
struct Node
{
    int l, r;
    int f[5][5];
} tr[N << 2];
void pushup(int u)
{
    Node &l = tr[u << 1], &r = tr[u << 1 | 1], &root = tr[u];
    root.f[1][1] = l.f[1][1] * r.f[1][1] % mod + l.f[1][2] * r.f[2][1] % mod;
    root.f[1][2] = l.f[1][1] * r.f[1][2] % mod + l.f[1][2] * r.f[2][2] % mod;
    root.f[2][1] = l.f[2][1] * r.f[1][1] % mod + l.f[2][2] * r.f[2][1] % mod;
    root.f[2][2] = l.f[2][1] * r.f[1][2] % mod + l.f[2][2] * r.f[2][2] % mod;
}
void build(int u, int l, int r)
{
    tr[u] = {l, r};
    if (l == r)
    {
        for (int j = 1; j <= 2; j++)
            for (int k = 1; k <= 2; k++)
                tr[u].f[j][k] = a[l][j][k];
        return;
    }
    int mid = l + r >> 1;
    build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    pushup(u);
}

Node merge(Node l, Node r)
{
    Node ans;
    ans.f[1][1] = l.f[1][1] * r.f[1][1] % mod + l.f[1][2] * r.f[2][1] % mod;
    ans.f[1][2] = l.f[1][1] * r.f[1][2] % mod + l.f[1][2] * r.f[2][2] % mod;
    ans.f[2][1] = l.f[2][1] * r.f[1][1] % mod + l.f[2][2] * r.f[2][1] % mod;
    ans.f[2][2] = l.f[2][1] * r.f[1][2] % mod + l.f[2][2] * r.f[2][2] % mod;
    return ans;
}

Node query(int u, int l, int r)
{
    if (tr[u].l == l && tr[u].r == r)
    {
        return tr[u];
    }
    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
        {
            Node left = query(u << 1, l, mid);
            Node right = query(u << 1 | 1, mid + 1, r);
            Node ans = merge(left, right);
            return ans;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    cin >> mod >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= 2; j++)
            for (int k = 1; k <= 2; k++)
                cin >> a[i][j][k];
    build(1, 1, n);

    while (m--)
    {
        int l, r;
        cin >> l >> r;
        auto ans = query(1, l, r).f;
        for (int i = 1; i <= 2; i++)
            for (int j = 1; j <= 2; j++)
                cout << ans[i][j] % mod << " \n"[j == 2];
        cout << endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值