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 ...
随机推荐
- C# DataGridview用NPOI导出Excel文件
导出excel我用的是nuget 的NPOI,直接在项目中添加的,引用到项目中,下面是截图: 下面我把ExcelHelper贴出来 public static class ExcelHelper { ...
- 转:C#中的多态
封装.继承.多态,面向对象的三大特性,前两项理解相对容易,但要理解多态,特别是深入的了解,对于初学者而言可能就会有一定困难了.我一直认为学习OO的最好方法就是结合实践,封装.继承在实际工作中的应用随处 ...
- flask 的管理模块的功能add_template_global、send_from_directory
add_template_global方法 全局模板函数 add_template_global 装饰器直接将函数注册为模板全局函数. add_template_global 这个方式是自定义的全局函 ...
- SQL脚本运行
$v=New-Object -ComObject wscript.shell#也可以使用反单引号(`)字符来强制PowerShell将单引号或双引号解释为文本,0不显示命令提示符窗口$v.run(&q ...
- Oracle恢复删除数据
可以通过SCN和时间戳两种方法来恢复. 一.通过SCN恢复删除且已经提交的数据 查询当前SCN select current_scn from v$database; 如图: 缩小范围进行查询 查询到 ...
- amazon interview
I'll be sitting for an Amazon interview in 3 months. Which website should I use to practice: SPOJ, H ...
- #002 WebStrom Live Templete 使用说明
WebStrom Live Template 使用说明 2016-03-30 20:33:52 星期三 WebStrom是前端一个强大的开发IDE.目前前端主要的开发工具有 Sublime T ...
- 最新版本2018.1.1webstorm安装、汉化、破解教程
一.安装(下载与激活) 1.官网下载安装包https://www.jetbrains.com/webstorm/ 2.开始安装 3.选择安装目录,点击下一步 4.勾选64位,点击下一步 5.继续下一步 ...
- CF585D Lizard Era: Beginning
嘟嘟嘟 题面我是不会咕的(没有真香):有\(n(n \leqslant 25)\)个任务和三个人,每次任务给出每个人能得到的值,每次任务选两个人,使\(n\)个任务结束后三个人得到的值是一样的,且尽量 ...
- docker 部署 redmine 项目管理软件
最近部署一套redmine项目管理程序, ruby部署各种问题,用docker 直接run, 简单方便. . docker run --name=mysql-redmine -d -p : -v /d ...