Solution -「SP 6779」GSS7
\(\mathcal{Description}\)
给定一棵 \(n\) 个点的带点权树,\(q\) 次操作:
- 路径点权赋值。
- 询问路径最大子段和(可以为空)。
\(n,q\le10^5\)。
\(\mathcal{Solution}\)
嘛……其实就是 GSS3 搬到树上 qwq。应该可以熟练地列出转移矩阵了叭,设 \(f(u)\) 为以 \(u\) 为端点的最大子段和,\(g(u)\) 为前缀最大子段和,\(s_u\) 为 \(u\) 的重儿子(这题来练练树剖 www),有:
\]
注意在树剖跳重链求答案的时候,必须注意矩乘顺序。例如对于路径 \((u,v)\),钦定 \(u\) 为路径起点,当 \(u\) 向上跳时,转移矩阵按 DFN 降序;当 \(v\) 向上跳时转移矩阵按 DFN 升序,所以线段树应维护两个乘法顺序的矩阵积。
这道题有些卡常(而且我常数貌似很大 qwq),所以手玩一下转移矩阵的幂,发现:
\]
就可以 \(\mathcal O(1)\) 求出矩阵幂了。
\(\mathcal{Code}\)
虽然长,但我觉得代码颜值挺高的 www。(大雾
#include <cstdio>
# ifdef LOCAL_DEBUG
const int MAXN = 5;
# else
const int MAXN = 1e5;
# endif
const int NINF = -( 1ll << 30 );
int n, m, ecnt, a[MAXN + 5], head[MAXN + 5];
int fa[MAXN + 5], dep[MAXN + 5], siz[MAXN + 5], son[MAXN + 5];
int dfc, dfn[MAXN + 5], ref[MAXN + 5], top[MAXN + 5];
inline int max_ ( const int a, const int b ) { return a > b ? a : b; }
inline char fgc () {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && ( q = buf + fread ( p = buf, 1, 1 << 17, stdin ), p == q ) ? EOF : *p ++;
}
inline int rint () {
# ifdef LOCAL_DEBUG
# define fgc getchar
# endif
int x = 0, f = 1; char s = fgc ();
for ( ; s < '0' || '9' < s; s = fgc () ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = fgc () ) x = x * 10 + ( s ^ '0' );
return x * f;
}
inline void wint ( int x ) {
if ( x < 0 ) putchar ( '-' ), x = -x;
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
}
struct Edge { int to, nxt; } graph[MAXN * 2 + 5];
inline void link ( const int s, const int t ) {
graph[++ ecnt] = { t, head[s] };
head[s] = ecnt;
}
struct Matrix {
int mat[3][3];
Matrix (): mat { NINF, NINF, NINF, NINF, NINF, NINF, NINF, NINF, NINF } {}
inline int* operator [] ( const int key ) { return mat[key]; }
inline Matrix operator * ( Matrix t ) {
Matrix ret;
for ( int i = 0; i < 3; ++ i ) {
for ( int k = 0; k < 3; ++ k ) {
for ( int j = 0; j < 3; ++ j ) {
ret[i][j] = max_ ( ret[i][j], mat[i][k] + t[k][j] );
}
}
}
return ret;
}
};
inline Matrix identity () {
static Matrix I;
I[0][0] = I[1][1] = I[2][2] = 0;
return I;
}
inline Matrix make ( const int v ) {
Matrix A;
A[0][0] = A[0][2] = A[1][2] = A[2][2] = 0;
A[0][1] = A[1][1] = v;
return A;
}
inline Matrix power ( const int v, const int k ) {
Matrix A;
A[0][0] = A[2][2] = 0;
A[0][1] = max_ ( v, k * v );
A[0][2] = A[1][2] = max_ ( 0, k * v );
A[1][1] = k * v;
return A;
}
struct SegmentTree {
Matrix S[2][MAXN * 2 + 5]; int tag[MAXN * 2 + 5];
inline int id ( const int l, const int r ) { return ( l + r ) | ( l != r ); }
inline void pushup ( const int l, const int r ) {
int rt = id ( l, r ), mid = l + r >> 1, lc = id ( l, mid ), rc = id ( mid + 1, r );
S[0][rt] = S[0][lc] * S[0][rc], S[1][rt] = S[1][rc] * S[1][lc];
}
inline void pushas ( const int l, const int r, const int v ) {
int rt = id ( l, r );
S[0][rt] = S[1][rt] = power ( v, r - l + 1 ), tag[rt] = v;
}
inline void pushdn ( const int l, const int r ) {
int rt = id ( l, r ), mid = l + r >> 1;
if ( tag[rt] == NINF ) return ;
pushas ( l, mid, tag[rt] ), pushas ( mid + 1, r, tag[rt] );
tag[rt] = NINF;
}
inline void build ( const int l, const int r ) {
int rt = id ( l, r ), mid = l + r >> 1;
tag[rt] = NINF;
if ( l == r ) return void ( S[0][rt] = S[1][rt] = make ( a[ref[l]] ) );
build ( l, mid ), build ( mid + 1, r );
pushup ( l, r );
}
inline void assign ( const int l, const int r, const int al, const int ar, const int v ) {
int mid = l + r >> 1;
if ( al <= l && r <= ar ) return pushas ( l, r, v );
pushdn ( l, r );
if ( al <= mid ) assign ( l, mid, al, ar, v );
if ( mid < ar ) assign ( mid + 1, r, al, ar, v );
pushup ( l, r );
}
inline Matrix query ( const int l, const int r, const int ql, const int qr, const bool type ) {
int rt = id ( l, r ), mid = l + r >> 1;
if ( ql <= l && r <= qr ) return S[type][rt];
pushdn ( l, r );
if ( qr <= mid ) return query ( l, mid, ql, qr, type );
else if ( mid < ql ) return query ( mid + 1, r, ql, qr, type );
else return ! type ?
query ( l, mid, ql, qr, 0 ) * query ( mid + 1, r, ql, qr, 0 ):
query ( mid + 1, r, ql, qr, 1 ) * query ( l, mid, ql, qr, 1 );
}
} st;
inline void DFS1 ( const int u, const int f ) {
dep[u] = dep[fa[u] = f] + ( siz[u] = 1 );
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ f ) {
DFS1 ( v, u ), siz[u] += siz[v];
if ( siz[son[u]] < siz[v] ) son[u] = v;
}
}
}
inline void DFS2 ( const int u, const int tp ) {
ref[dfn[u] = ++ dfc] = u, top[u] = tp;
if ( son[u] ) DFS2 ( son[u], tp );
for ( int i = head[u], v; i; i = graph[i].nxt ) {
if ( ( v = graph[i].to ) ^ fa[u] && v ^ son[u] ) {
DFS2 ( v, v );
}
}
}
inline void assignChain ( int u, int v, const int w ) {
while ( top[u] ^ top[v] ) {
if ( dep[top[u]] < dep[top[v]] ) u ^= v ^= u ^= v;
st.assign ( 1, n, dfn[top[u]], dfn[u], w );
u = fa[top[u]];
}
if ( dep[u] < dep[v] ) u ^= v ^= u ^= v;
st.assign ( 1, n, dfn[v], dfn[u], w );
}
inline int queryChain ( int u, int v ) {
Matrix A ( identity () ), B ( identity () );
while ( top[u] ^ top[v] ) {
if ( dep[top[u]] < dep[top[v]] ) {
B = st.query ( 1, n, dfn[top[v]], dfn[v], 0 ) * B;
v = fa[top[v]];
} else {
A = A * st.query ( 1, n, dfn[top[u]], dfn[u], 1 );
u = fa[top[u]];
}
}
if ( dep[u] > dep[v] ) A = A * st.query ( 1, n, dfn[v], dfn[u], 1 );
else B = st.query ( 1, n, dfn[u], dfn[v], 0 ) * B;
A = A * B;
return max_ ( A[0][1], A[0][2] );
}
int main () {
n = rint ();
for ( int i = 1; i <= n; ++ i ) a[i] = rint ();
for ( int i = 1, u, v; i < n; ++ i ) {
u = rint (), v = rint ();
link ( u, v ), link ( v, u );
}
DFS1 ( 1, 0 ), DFS2 ( 1, 1 );
st.build ( 1, n );
for ( int q = rint (), op, a, b, c; q --; ) {
op = rint (), a = rint (), b = rint ();
if ( op & 1 ) {
wint ( queryChain ( a, b ) );
putchar ( '\n' );
} else {
c = rint ();
assignChain ( a, b, c );
}
}
return 0;
}
Solution -「SP 6779」GSS7的更多相关文章
- Solution -「ARC 104E」Random LIS
\(\mathcal{Description}\) Link. 给定整数序列 \(\{a_n\}\),对于整数序列 \(\{b_n\}\),\(b_i\) 在 \([1,a_i]\) 中等概率 ...
- Solution -「CTS 2019」「洛谷 P5404」氪金手游
\(\mathcal{Description}\) Link. 有 \(n\) 张卡牌,第 \(i\) 张的权值 \(w_i\in\{1,2,3\}\),且取值为 \(k\) 的概率正比于 \ ...
- Solution -「BZOJ 3812」主旋律
\(\mathcal{Description}\) Link. 给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
- Solution -「Gym 102759G」LCS 8
\(\mathcal{Description}\) Link. 给定 \(m\),和长度为 \(n\),字符集为大写字母的字符串 \(s\),求字符集相同且等长的字符串 \(t\) 的数量,使 ...
- Solution -「ZJOI 2019」「洛谷 P5326」开关
\(\mathcal{Description}\) Link. 有 \(n\) 个开关,初始时所有开关的状态为 \(0\).给定开关的目标状态 \(s_1,s_2,\cdots,s_n\).每 ...
- Solution -「简单 DP」zxy 讲课记实
魔法题位面级乱杀. 「JOISC 2020 Day4」治疗计划 因为是不太聪明的 Joker,我就从头开始理思路了.中途也会说一些和 DP 算法本身有关的杂谈,给自己的冗长题解找借口. 首先,治疗方案 ...
- Solution -「基环树」做题记录
写的大多只是思路,比较简单的细节和证明过程就不放了,有需者自取. 基环树简介 简单说一说基环树吧.由名字扩展可得这是一类以环为基础的树(当然显然它不是树. 通常的表现形式是一棵树再加一条非树边,把图画 ...
- Solution -「WC 2022」秃子酋长
\(\mathscr{Description}\) Link. (It's empty temporarily.) 给定排列 \(\{a_n\}\),\(q\) 次询问,每次给出 \([l,r ...
随机推荐
- js实现工具函数中groupBy数据分组
数据 this.tableData = [ {id: 1, name: '测试', number: 1, price: 0}, {id: 2, name: '测试', number: 1, price ...
- 使用VUE组件创建SpreadJS自定义单元格(二)
在上篇中,我们介绍了如何通过设置runtimeCompiler为true,在Vue中实现了动态创建电子表格组件.想了解具体内容可看点击查看使用VUE组件创建SpreadJS自定义单元格(一). 但是在 ...
- Sentry 企业级数据安全解决方案 - Relay PII 和数据清理
本文档描述了一种我们希望最终对用户隐藏的配置格式.该页面仍然存在的唯一原因是当前 Relay 接受这种格式以替代常规数据清理设置. 以下文档探讨了 Relay 使用和执行的高级数据清理配置的语法和语义 ...
- promise到底怎么理解
Promise的含义promise是异步编程的一种解决方法.所谓promise,简单说是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,从语法上说,promise是一个对象,从 ...
- WebGL 与 WebGPU 比对[1] 前奏
目录 1 为什么是 WebGPU 而不是 WebGL 3.0 显卡驱动 图形 API 的简单年表 WebGL 能运行在各个浏览器的原因 WebGPU 的名称由来 2 与 WebGL 比较编码风格 Op ...
- 微服务架构 | 3.1 Netflix Eureka 注册中心
目录 前言 1. Eureka 基础知识 1.1 Eureka 模型中的服务器与客户端 1.2 Eureka 的 30s 启动机制 1.3 Eureka 为什么注册服务的 IP ,而不是主机名 1.4 ...
- Javascript实现让小图片一直跟着鼠标移动
Javascript实现让小图片一直跟着鼠标移动实例 注意:图片可能加载不出来,注意更换 <!doctype html> <html> <head> <met ...
- TextBox,RichTextBox设置行高
/// <summary> /// 设置行距 /// </summary> /// <param name="ctl">控件</param ...
- 5.12-jsp分页功能学习
1.分页功能相关资料查询 分页须知知识点: (1)JDBC2.0的可滚动结果集. (2)HTTP GET请求. 一.可滚动结果集 Connection con = DriverManager.g ...
- @WebServlet注解(Servlet注解)
@WebServlet 注解的属性 @WebServlet 用于将一个类声明为 Servlet,该注解会在部署时被容器处理,容器根据其具体的属性配置将相应的类部署为 Servlet.该注解具有下表给出 ...