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 的博客
引入广义矩阵乘法:
\]
这样的话,我们首先写出动态规划的柿子:
设\(f_i\)表示以\(i\)结尾的最大子段和,\(g_i\)表示\([1,i]\)的最大子段和
于是
\]
欢乐地写出矩乘的柿子:
\]
妙哉
因为矩阵乘法具有结合律,于是可以用线段树维护
当然资瓷单点修改和查询区间最大子段和了
代码
#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\n", 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 题意翻译 n 个数,q 次操作 操作0 x y把A_xAx 修改为yy 操作1 l r询问区间[l, r] ...
- SP1716 GSS3 - Can you answer these queries III(单点修改,区间最大子段和)
题意翻译 nnn 个数, qqq 次操作 操作0 x y把 AxA_xAx 修改为 yyy 操作1 l r询问区间 [l,r][l, r][l,r] 的最大子段和 题目描述 You are give ...
- SP1716 GSS3 - Can you answer these queries III 线段树
问题描述 [LG-SP1716](https://www.luogu.org/problem/SP1716] 题解 GSS 系列的第三题,在第一题的基础上带单点修改. 第一题题解传送门 在第一题的基础 ...
- SP1716 GSS3 - Can you answer these queries III - 动态dp,线段树
GSS3 Description 动态维护最大子段和,支持单点修改. Solution 设 \(f[i]\) 表示以 \(i\) 为结尾的最大子段和, \(g[i]\) 表示 \(1 \sim i\) ...
- SPOJ GSS3 Can you answer these queries III[线段树]
SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...
- 数据结构(线段树):SPOJ GSS3 - Can you answer these queries III
GSS3 - Can you answer these queries III You are given a sequence A of N (N <= 50000) integers bet ...
- 【SP1716】GSS3 - Can you answer these queries III(动态DP)
题目链接 之前用线段树写了一遍,现在用\(ddp\)再写一遍. #include <cstdio> #define lc (now << 1) #define rc (now ...
- 题解 SP1716 【GSS3 - Can you answer these queries III】
\[ Preface \] 没有 Preface. \[ Description \] 维护一个长度为 \(n\) 的数列 \(A\) ,需要支持以下操作: 0 x y 将 \(A_x\) 改为 \( ...
- 题解【SP1716】GSS3 - Can you answer these queries III
题目描述 You are given a sequence \(A\) of \(N (N <= 50000)\) integers between \(-10000\) and \(10000 ...
随机推荐
- .Net Core+Vue.js+ElementUI 实现前后端分离
.Net Core+Vue.js+ElementUI 实现前后端分离 Tags: Vue 架构 前端采用:Vue.js.Element-UI.axios 后端采用:.Net Core Mvc 本项目是 ...
- springMVC入门-05
接着上一讲,介绍如何查询单个数据,此处介绍show()方法的实现.显示单条数据需要使用Users对象中的一个字段作为入参来进行对象查询,将查询出来的数据放在Model中,并且将model中的user对 ...
- Common administrative commands in Red Hat Enterprise Linux 5, 6, and 7
https://access.redhat.com/articles/1189123 Common administrative commands in Red Hat Enterprise Linu ...
- C++:sprintf()的用法(转)
转:http://blog.csdn.net/masikkk/article/details/5634886 更多:http://blog.csdn.net/zjuwispersure/article ...
- T-SQL 标识符
在T-SQL语言中,对SQLServer数据库及其数据对象(比如表.索引.视图.存储过程.触发器等)需要以名称来进行命名并加以区分,这些名称就称为标识符. 通常情况下,SQLServer数据库.数据库 ...
- Java编程练习题
曾经,有人说过,没有刷题的人生是不完整的.看了几天Java,我试着做了几道练习题,好让我的人生完整一点.(偷笑--)这里挑了一些题来跟大家分享,本文不定期更新. 题目集 1. 最后一个单词的长度 ...
- awk.md
简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的行编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分 ...
- 1202. [HNOI2005]狡猾的商人【贪心 或 并查集】
Description 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 ...
- 「GXOI / GZOI2019」与或和
题目 广西和贵州的省选?好像很神仙的样子啊 之后发现这是一道水题 我们显然应该拆位考虑 显然我们应该对于每一位都拆一下看看这一位是\(0/1\) 显然我们如果找到一个全是\(1\)的矩阵,那么这一位的 ...
- 【node.js】全局变量、常用工具、文件系统
学习链接:http://www.runoob.com/nodejs/nodejs-global-object.html 在 JavaScript 中,通常 window 是全局对象, 而 Node.j ...