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 ...
随机推荐
- UIButton的两种block传值方式
UIButton的两种block传值方式 方式1 - 作为属性来传值 BlockView.h 与 BlockView.m // // BlockView.h // Block // // Create ...
- [翻译] TSMessages
TSMessages https://github.com/KrauseFx/TSMessages This library provides an easy to use class to show ...
- UIWebView如何加载本地图片
UIWebView如何加载本地图片 UIWebView加载本地图片是有实用价值的.比方说,有时候我们需要本地加载静态页来显示相关帮助信息,而这些帮助信息当中含有很多很多的富文本,用代码实现难度较大,这 ...
- iOS手势处理
iOS手势处理 iOS手势有着如下几种: UITapGestureRecognizer UIPinchGestureRecognizer UIRotationGestureRecognizer UIS ...
- PHP-7的FPM服务的启动
1.PHP 7的FPM服务位置:/ect/init.d/php7.0-fpm 2.启动:sudo service php7.0-fpm reload
- 如何从Microsoft web platform installer取得离线安装包
有一架visual studio 2012的开发环境A由于某种原因无法链接internet, 于是乎安装officetoolsforvisual2012就有问题了. 从微软的官网上只可以下载 offi ...
- 【模块化】 RequireJS入门教程总结与推荐
之所以学习RequireJS,肯定对 模块化有一定的理解.这里有几篇学习 RequireJS的文章,推荐给大家去学习. Javascript模块化编程(一):模块的写法 Javascript模块化编程 ...
- 【转】.NET Core基于. csproj 配置文件发布项目
一.前言 .NET工具链在最新的Preview3版本中,引入了新的MSBuild项目系统,项目文件又回归了.csproj的XML文件来管理,项目文件.包引用.程序集引用..NET Core工具集.发布 ...
- 3、Django下载与简介
第1节:MVC与MTV模型 1.1 MVC Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的方式连接在一 ...
- jQuery获取radio选中项checked的几种方法
如何知道radio哪个选项被选中了,也就是获取checked的radio项.这是个很简单的任务,这里我总结了几个常用的方法,体验一下jQuery的灵活. 具体的 HTML 和 jQuery 代码可以右 ...