SP1716 GSS3 - Can you answer these queries III

Posted cj-xxz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SP1716 GSS3 - Can you answer these queries III相关的知识,希望对你有一定的参考价值。

题面

题解

相信大家写过的传统做法像这样:(这段代码蒯自Karry5307的题解

struct SegmentTree{
    ll l,r,prefix,suffix,sum,maxn;  
};

//...

inline void update(ll node)
{
    ll res;
    tree[node].sum=tree[node<<1].sum+tree[(node<<1)|1].sum;
    tree[node].maxn=max(tree[node<<1].maxn,tree[(node<<1)|1].maxn);
    res=tree[node<<1].suffix+tree[(node<<1)|1].prefix;
    tree[node].maxn=max(tree[node].maxn,res);
    res=tree[node<<1].sum+tree[(node<<1)|1].prefix;
    tree[node].prefix=max(tree[node<<1].prefix,res);
    res=tree[node<<1].suffix+tree[(node<<1)|1].sum;
    tree[node].suffix=max(tree[(node<<1)|1].suffix,res);
}

//...

有没有觉得这种做法有些麻烦

这里将一种硬核做法:动态dp

这个部分参考了GKxx 的博客

引入广义矩阵乘法:
[ mathrm{C} = mathrm{A} * mathrm{B} Leftrightarrow mathrm{C}_{i,j} = max_kleft{mathrm{A}_{i,k} + mathrm{B}_{k,j} ight} ]
这样的话,我们首先写出动态规划的柿子:

(f_i)表示以(i)结尾的最大子段和,(g_i)表示([1,i])的最大子段和

于是
[ egin{aligned} f_i &= max(f_{i-1} + a_i, a_i) \ g_i &= max(g_{i-1}, f_i) end{aligned} ]
欢乐地写出矩乘的柿子:
[ egin{bmatrix}f_{i-1} & g_{i-1} & 0end{bmatrix} imesegin{bmatrix}a_i & a_i & -infty\-infty & 0 & -infty\a_i & a_i & 0end{bmatrix}=egin{bmatrix}f_i & g_i & 0end{bmatrix} ]
妙哉

因为矩阵乘法具有结合律,于是可以用线段树维护

当然资瓷单点修改和查询区间最大子段和了

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);
#define clear(x, y) memset(x, y, sizeof(x));

inline int read()
{
    int data = 0, w = 1;
    char ch = getchar();
    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if(ch == '-') w = -1, ch = getchar();
    while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return data * w;
}

const int maxn(50010), INF(0x3f3f3f3f);
template<typename T> inline void chkmax(T &a, const T &b)
    { return (void) (a < b ? a = b : 0); }
struct Matrix
{
    int a[3][3];
    inline int *operator [] (const int &x) { return a[x]; }
    inline const int *operator [] (const int &x) const { return a[x]; }
} mat[maxn << 2]; int n, Q, a[maxn];

inline Matrix operator * (const Matrix &a, const Matrix &b)
{
    Matrix c; for(int i = 0; i < 3; i++) c[i][0] = c[i][1] = c[i][2] = -INF;
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            for(int k = 0; k < 3; k++)
                chkmax(c[i][k], a[i][j] + b[j][k]);
    return c;
}

void build(int root = 1, int l = 1, int r = n)
{
    if(l == r)
    {
        Matrix &o = mat[root]; o[0][1] = o[2][0] = o[2][1] = -INF;
        o[0][0] = o[0][2] = o[1][0] = o[1][2] = a[l];
        o[1][1] = o[2][2] = 0; return;
    }
    int mid = (l + r) >> 1, lson = root << 1, rson = lson | 1;
    build(lson, l, mid), build(rson, mid + 1, r);
    mat[root] = mat[lson] * mat[rson];
}

void update(int id, int v, int root = 1, int l = 1, int r = n)
{
    if(l == r) return (void)
        (mat[root][0][0] = mat[root][0][2]
         = mat[root][1][0] = mat[root][1][2] = v);
    int mid = (l + r) >> 1, lson = root << 1, rson = lson | 1;
    if(id <= mid) update(id, v, lson, l, mid);
    else update(id, v, rson, mid + 1, r);
    mat[root] = mat[lson] * mat[rson];
}

Matrix query(int ql, int qr, int root = 1, int l = 1, int r = n)
{
    if(ql <= l && r <= qr) return mat[root];
    int mid = (l + r) >> 1, lson = root << 1, rson = lson | 1;
    if(qr <= mid) return query(ql, qr, lson, l, mid);
    if(ql >  mid) return query(ql, qr, rson, mid + 1, r);
    return query(ql, qr, lson, l, mid) * query(ql, qr, rson, mid + 1, r);
}

int main()
{
    n = read();
    for(RG int i = 1; i <= n; i++) a[i] = read();
    build(); Q = read();
    while(Q--)
    {
        int opt = read(), x = read(), y = read();
        if(opt)
        {
            Matrix ans = query(x, y);
            printf("%d
", std::max(ans[1][0], ans[1][2]));
        }
        else a[x] = y, update(x, y);
    }
    return 0;
}

以上是关于SP1716 GSS3 - Can you answer these queries III的主要内容,如果未能解决你的问题,请参考以下文章

SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III 线段树

题解 SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III

SP1716 GSS3 - Can you answer these queries III - 动态dp,线段树