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 ...
随机推荐
- 【Redis】命令学习笔记——列表(list)+集合(set)+有序集合(sorted set)(17+15+20个超全字典版)
本篇基于redis 4.0.11版本,学习列表(list)和集合(set)和有序集合(sorted set)相关命令. 列表按照插入顺序排序,可重复,可以添加一个元素到列表的头部(左边)或者尾部(右边 ...
- 使用CADisplayLink写秒表
使用CADisplayLink写秒表 效果: 源码: StopWatch.h 与 StopWatch.m // // StopWatch.h // ShowTime // // Created by ...
- 铁乐学python_day20_面向对象编程2
面向对象的组合用法 软件重用的重要方式除了继承之外还有另外一种方式,即:组合 组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合. 例:人狗大战,人类绑定上武器来对狗进行攻击: # 定 ...
- nginx alias
A path to the file is constructed by merely adding a URI to the value of the root directive. If a UR ...
- async/await actor promise 异步编程
Python协程:从yield/send到async/await http://blog.guoyb.com/2016/07/03/python-coroutine/ Async/Await替代Pro ...
- CF993E:Nikita and Order Statistics(FFT)
Description 给你一个数组 $a_{1 \sim n}$,对于 $k = 0 \sim n$,求出有多少个数组上的区间满足:区间内恰好有 $k$ 个数比 $x$ 小.$x$ 为一个给定的数. ...
- Hive学习之路 (十八)Hive的Shell操作
一.Hive的命令行 1.Hive支持的一些命令 Command Description quit Use quit or exit to leave the interactive shell. s ...
- mysql 5.5.42 更改数据目录 centos 6.5环境
1.新建新数据目录,检查目录属主机权限,一般情况下属于mysql组,myql用户,因为我们安装mysql的时候会新建该账户和组. 2.目录权限检查完毕,停止数据库服务. 3.移动数据目录 ,我用的是m ...
- better-scroll在vue中的坑
在我们日常的移动端项目开发中,处理滚动列表是再常见不过的需求了,以滴滴为例,可以是这样竖向滚动的列表,如图所示: 也可以是横向滚动的导航栏,如图所示: 可以打开“微信 —> 钱包—>滴滴出 ...
- json和jsonp的问题
本文转载自:http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 前言: 说到AJAX就会不可避免的面临 ...