线段树, 但是数字怎么存呢?
查看原帖
线段树, 但是数字怎么存呢?
324632
Skeleton_Huo楼主2022/10/3 20:10

赛时直接用的long long,30pts。把大于2^30的数限定为2^30+1是45pts,多了性质A的分。直接改成__int128_t是85pts。

上述的第一种改良方法应该是可行的(见人AC了),但不知道漏了什么。

代码(大样例过了):

#include <iostream>
#include <cstdio>

#define int long long

namespace io {
    inline int read() {
        char ch = getchar(); int flag = 1, res = 0;
        while (ch < '0' || ch > '9') { if (ch == '-') flag = -1; ch = getchar(); }
        while (ch >= '0' && ch <= '9') { res = (res << 1) + (res << 3) + ch - '0'; ch = getchar(); }
        return flag * res;
    }
    inline void write(int x) {
        if (x < 0) putchar('-'), x = -x;
        if (x > 9) write(x / 10);
        putchar(x % 10 + '0');
    }
}

using namespace std;
using namespace io;

const int N = 200010, M = (1 << 30) + 1;

int n, q;
int a[N];

class SegTree {
private:
    struct Node {
        int sum;
        int maxl, maxr, maxn;
        int minl, minr, minn;   // 定义...
    } c[N << 2];

    void calc(Node& rt, Node lc, Node rc) {
        rt.sum = lc.sum * rc.sum;
        rt.maxl = max(lc.maxl, max(lc.sum * rc.maxl, lc.sum * rc.minl));
        rt.maxr = max(rc.maxr, max(rc.sum * lc.maxr, rc.sum * lc.minr));
        rt.maxn = max(max(lc.maxn, rc.maxn), max(lc.maxr * rc.maxl, lc.minr * rc.minl));
        rt.minl = min(lc.minl, min(lc.sum * rc.minl, lc.sum * rc.maxl));
        rt.minr = min(rc.minr, min(rc.sum * lc.minr, rc.sum * lc.maxr));
        rt.minn = min(min(lc.minn, rc.minn), min(lc.minr * rc.maxl, lc.maxr * rc.minl));
        rt.sum = min(rt.sum, M);
        rt.maxl = min(rt.maxl, M);
        rt.maxr = min(rt.maxr, M);
        rt.maxn = min(rt.maxn, M);
        rt.minl = max(rt.minl, -M);
        rt.minr = max(rt.minr, -M);
        rt.minn = max(rt.minn, -M);         // 这里是我对第一中改良方法的处理
    }

    void update(Node& res, Node val) {
        if (res.sum == 0) {
            res = val;
            return;
        }
        Node tmp = res;
        calc(res, tmp, val);
    }

public:
    void buildTree(int p, int l, int r) {
        if (l == r) {
            if (a[l] > 0) 
                c[p] = (Node){a[l], a[l], a[l], a[l], 1, 1, 1};
            else
                c[p] = (Node){a[l], 1, 1, 1, a[l], a[l], a[l]};
            return;
        }
        int mid = l + (r - l >> 1);
        buildTree(p << 1, l, mid);
        buildTree(p << 1 | 1, mid + 1, r);
        calc(c[p], c[p << 1], c[p << 1 | 1]);
    }

    void change(int p, int l, int r, int x, int y) {
        if (l == r) {
            if (y > 0) 
                c[p] = (Node){y, y, y, y, 1, 1, 1};
            else
                c[p] = (Node){y, 1, 1, 1, y, y, y};
            return;
        }
        int mid = l + (r - l >> 1);
        if (x <= mid)
            change(p << 1, l, mid, x, y);
        else
            change(p << 1 | 1, mid + 1, r, x, y);
        calc(c[p], c[p << 1], c[p << 1 | 1]);
    }

    Node query(int p, int l, int r, int s, int t) {
        if (s <= l && r <= t)
            return c[p];
        int mid = l + (r - l >> 1);
        Node res = (Node){0, 0, 0, 0, 0, 0, 0};
        if (s <= mid)
            update(res, query(p << 1, l, mid, s, t));
        if (t > mid)
            update(res, query(p << 1 | 1, mid + 1, r, s, t));
        return res;
    }
} st;

signed main() {
    
    // freopen("T1ex2.in", "r", stdin);
    // freopen("a.out", "w", stdout);

    n = read(), q = read();

    for (int i = 1; i <= n; i++)
        a[i] = read();
    
    st.buildTree(1, 1, n);

    int opt, x, y;
    while (q--) {
        opt = read(), x = read(), y = read();
        if (opt == 1) {
            st.change(1, 1, n, x, y);
        } else {
            int ans = st.query(1, 1, n, x, y).maxn;
            if (ans == M)
                puts("Too large");
            else 
                write(ans), puts("");
        }
    }
    
    // puts(""), system("pause");

    return 0;
}
2022/10/3 20:10
加载中...