[ZJOI2011] 道馆之战(树链剖分)

problem

luogu-P4679

理解清楚题意又是一个世纪的更迭了

给定一个树,每个节点位置上实际放了两个节点。

然后若干次修改和查询。... 能走,#\## 不能走。

询问 u→vu\rightarrow vuv 的简单路径上最长能走的距离。(是强制从 uuu 开始,不是问最长子段哦)

同个节点位置上放的两个节点能否互通依旧遵循上面的规则。

solution

这种路径问题通常我们考虑树剖,如果涉及断边加边的动态操作就考虑 LCT\text{LCT}LCT

上树链剖分的板子,两个 dfs\text{dfs}dfs duangduang抡上去。

然后考虑线段树怎么维护信息能够合并。

我们定义每个节点位置上实际存在的两个节点分别为 0/10/10/1

线段树上每个节点维护区间 [l,r][l,r][l,r] 的信息:

  • lx[2]:llx[2]:llx[2]:l0/10/10/1 节点开始能走的最长距离。

  • rx[2]:rrx[2]:rrx[2]:r0/10/10/1 节点开始能走的最长距离。

  • mx[2][2]:lmx[2][2]:lmx[2][2]:l0/10/10/1rrr0/10/10/1 的最长距离。

    一定是从 lll0/10/10/1 开始走,且全程不被阻挡地成功走到 rrr0/10/10/1 的距离。

这有点类似线段树维护区间最大子段和的维护方式,但略有不同。

合并两个区间的时候,也是类似线段树维护区间最大子段和的做法。

  • lx[i]lx[i]lx[i]

    • 直接就是左儿子算的答案。lson→lx[i]lson\rightarrow lx[i]lsonlx[i]

    • 左儿子整个区间走完的最大值再加上右儿子的左端点位置上的某个节点开始往后走的最大值。

      但不清楚左儿子走到其右端点位置的哪个节点更优,需要枚举,右儿子的左端点位置同理。

      lson→mx[i][j]+rson→lx[j]lson\rightarrow mx[i][j]+rson\rightarrow lx[j]lsonmx[i][j]+rsonlx[j]

  • rx[i]rx[i]rx[i]

    • 直接右儿子算的答案。rson→rx[i]rson\rightarrow rx[i]rsonrx[i]

    • 右儿子整个区间走完的最大值再加上左儿子区间右端点位置上的某个节点开始往前走的最大值。

      同理需要枚举。

      rson→mx[i][j]+lson→lx[j]rson\rightarrow mx[i][j]+lson\rightarrow lx[j]rsonmx[i][j]+lsonlx[j]

  • mx[i][j]mx[i][j]mx[i][j]

    只能知道是从左儿子区间左端点位置的 iii 节点到右儿子区间右端点位置的 jjj 节点。

    但不清楚左儿子区间右端点位置的结束节点以及右儿子区间左端点位置的开始节点,同样需要枚举。

    且左儿子结束节点应与右儿子开始节点一样,不然走不过去。

    lson→mx[i][k]+rson→mx[k][j]lson\rightarrow mx[i][k]+rson\rightarrow mx[k][j]lsonmx[i][k]+rsonmx[k][j]

合并知道了,单点修改应该就能明白。这里不再赘述。可以看下面代码。

只说一点:因为要连续,所以如果是阻拦直接设成 −∞-\infty。 这样子就一定不可能使两段无法到达的区间答案在线段树上被错误合并。

最后需要注意一点。

我们树剖是从上往下剖,也就是说线段树上一个 [l,r][l,r][l,r] 区间,对应的是原树上一条从上往下的链的信息。

但实际上我们应该是 u→lca(u,v)→vu\rightarrow lca(u,v)\rightarrow vulca(u,v)v,在树上是先往上走再往下走。

那么往上走的信息就需要反转区间维护的信息。

所以树剖就不能写代码简化版(通过判断 u,vu,vu,v 所在重链的深度决定是否需要交换 u,vu,vu,v

u,vu,vu,v 地位是不同的。

最后答案就是从 uuu 位置的两个节点出发能走的最远距离的较大值,即 ans→lx[0/1]ans\rightarrow lx[0/1]anslx[0/1]

code

#include <bits/stdc++.h>
using namespace std;
#define maxn 50005
int n, m, cnt;
vector < int > G[maxn];
char op[maxn][5];
int f[maxn], siz[maxn], dep[maxn], son[maxn], top[maxn], dfn[maxn], id[maxn];namespace SGT {struct node { int lx[2], rx[2], mx[2][2];node() {memset( lx, 0, sizeof( lx ) );memset( rx, 0, sizeof( rx ) );memset( mx, 0, sizeof( mx ) );} }t[maxn << 2];#define lson now << 1#define rson now << 1 | 1#define mid  (l + r >> 1)node operator + ( node ls, node rs ) {node ans;memset( ans.mx, -0x3f, sizeof( ans.mx ) );for( int i = 0;i <= 1;i ++ )for( int j = 0;j <= 1;j ++ ) {ans.lx[i] = max( ans.lx[i], max( ls.lx[i], ls.mx[i][j] + rs.lx[j] ) );ans.rx[i] = max( ans.rx[i], max( rs.rx[i], rs.mx[j][i] + ls.rx[j] ) );for( int k = 0;k <= 1;k ++ )ans.mx[i][j] = max( ans.mx[i][j], ls.mx[i][k] + rs.mx[k][j] );}return ans;}node init( char *op ) {node ans;if( op[0] == '.' and op[1] == '.' ) {ans.lx[0] = ans.lx[1] = ans.rx[0] = ans.rx[1] = 2;ans.mx[0][0] = ans.mx[1][1] = 1;ans.mx[0][1] = ans.mx[1][0] = 2;}else if( op[0] == '.' or op[1] == '.' ) {int d = op[1] == '.';memset( ans.mx, -0x3f, sizeof( ans.mx ) );ans.lx[d] = ans.rx[d] = ans.mx[d][d] = 1;ans.lx[!d] = ans.rx[!d] = 0;           }else {ans.lx[0] = ans.lx[1] = ans.rx[0] = ans.rx[1] = 0;memset( ans.mx, -0x3f, sizeof( ans.mx ) );}return ans;}void reverse( node &ans ) {swap( ans.lx[0], ans.rx[0] );swap( ans.lx[1], ans.rx[1] );swap( ans.mx[0][1], ans.mx[1][0] );}void modify( int now, int l, int r, int p ) {if( l == r ) { t[now] = init( op[id[l]] ); return; }if( p <= mid ) modify( lson, l, mid, p );else modify( rson, mid + 1, r, p );t[now] = t[lson] + t[rson];}node query( int now, int l, int r, int L, int R ) {if( L <= l and r <= R ) return t[now];if( R <= mid ) return query( lson, l, mid, L, R );else if( mid < L ) return query( rson, mid + 1, r, L, R );else return query( lson, l, mid, L, R ) + query( rson, mid + 1, r, L, R );}
}namespace Qtree {void dfs1( int u, int fa ) {f[u] = fa, siz[u] = 1, dep[u] = dep[fa] + 1;for( int v : G[u] ) {if( v == fa ) continue;else dfs1( v, u );siz[u] += siz[v];if( siz[v] > siz[son[u]] ) son[u] = v;}}void dfs2( int u, int t ) {id[dfn[u] = ++ cnt] = u, top[u] = t;if( son[u] ) dfs2( son[u], t );else return;for( int v : G[u] ) if( v ^ f[u] and v ^ son[u] ) dfs2( v, v );}int query( int x, int y ) {SGT :: node ans1, ans2, ans;while( top[x] ^ top[y] ) {if( dep[top[x]] > dep[top[y]] )ans1 = SGT :: query( 1, 1, n, dfn[top[x]], dfn[x] ) + ans1, x = f[top[x]];elseans2 = SGT :: query( 1, 1, n, dfn[top[y]], dfn[y] ) + ans2, y = f[top[y]];}if( dep[x] > dep[y] ) ans1 = SGT :: query( 1, 1, n, dfn[y], dfn[x] ) + ans1;else ans2 = SGT :: query( 1, 1, n, dfn[x], dfn[y] ) + ans2;reverse( ans1 );ans = ans1 + ans2;return max( ans.lx[0], ans.lx[1] );}
}int main() {scanf( "%d %d", &n, &m );for( int i = 1, u, v;i < n;i ++ ) {scanf( "%d %d", &u, &v );G[u].push_back( v );G[v].push_back( u );}Qtree :: dfs1( 1, 0 );Qtree :: dfs2( 1, 1 );for( int i = 1;i <= n;i ++ ) {scanf( "%s", op[i] );SGT :: modify( 1, 1, n, dfn[i] );}char opt[5]; int u, v;while( m -- ) {scanf( "%s", opt );if( opt[0] == 'C' ) {scanf( "%d", &u );scanf( "%s", op[u] );SGT :: modify( 1, 1, n, dfn[u] );}else {scanf( "%d %d", &u, &v );printf( "%d\n", Qtree :: query( u, v ) );}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316452.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[NOI2008] 志愿者招募(线性规划-对偶问题-费用流)

problem luogu-P3980 solution 志愿者连续工作 [si,ti][s_i,t_i][si​,ti​] 天&#xff0c;我们可以提炼出网络流二十四题中《最长k可重区间集问题》的模型。 同样地&#xff0c;把 1∼n1\sim n1∼n 天抽象成一条 1∼n11\sim n11∼n1 个点的链条。 源点 s→1s\rightarrow…

互达的集合(线段树)

problem 给定数组 l,rl,rl,r。求有多少个非空集合 SSS&#xff0c;满足 ∀i,j∈Sli≤j≤ri\forall_{i,j\in S}\ l_i\le j\le r_i∀i,j∈S​ li​≤j≤ri​。 集合内对于任意一个点而言&#xff0c;其余点均能被自己的范围覆盖到。 n≤2e5n\le 2e5n≤2e5。 solution 分享一下…

【学习笔记】线性规划与对偶问题和LP对偶费用流([ZJOI2013]防守战线题解)

线性规划与对偶问题 原问题&#xff1a; min⁡{7x1x25x3}s.t.{x1−x23x3≥105x12x2−x3≥6xi≥0\min\{7x_1x_25x_3\} \\ s.t.\begin{cases} x_1-x_23x_3\ge 10\\ 5x_12x_2-x_3\ge 6\\ x_i\ge 0\end{cases} min{7x1​x2​5x3​}s.t.⎩⎪⎨⎪⎧​x1​−x2​3x3​≥105x1​2x2​−…

【学习笔记】DAG / 一般有向图的支配树 / 灭绝树

定义与声明 一个有向图 GGG。给定一个起点 sss&#xff0c;假设 sss 能到达所有点。 若去掉某个点 iii 后&#xff0c;sss 无法到达 jjj&#xff0c;则称 iii 为 jjj 的支配点。 显然支配点存在传递关系。 以 sss 为根&#xff0c;使得对于任意节点 iii&#xff0c;其树上祖…

[ZJOI2014] 星系调查(树上差分 + 数学推式子)

problem luogu-P3340 题面写得那么长&#xff0c;其实说白了就是求一条直线&#xff0c;使得若干个点到这条直线的距离平方的和最小&#xff0c;求这个最小值。 solution 我超爱数学&#xff0c;数学就是我的命&#xff0c;我一天不学数学我就难受&#xff01; 假设拟合出…

[ZJOI2014] 璀璨光华(bfs建图 + dfs搜索)

problem luogu-P3342 solution 你感觉这道题没考什么&#xff0c;又感觉考了什么 通过样例以及题面&#xff0c;我们并未获取到『立方体每个小方块的编号是按一定规则命名』的信息。 也就是说&#xff0c;我们需要通过输入的每个小方块相邻的编号的信息来建出这个立方体的…

cf1523A. Game of Life

cf1523A. Game of Life 题意&#xff1a; 包含n个元素的数组&#xff0c;数值为1或0&#xff0c;如果一个元素为0&#xff0c;并且其周围正好只有一个为1的元素&#xff0c;那么下一刻本元素也会变成1. 给你一个数值&#xff0c;问你m次时刻后数组的状态 题解&#xff1a; …

SignalR 中丰富多彩的消息推送方式

在上一篇 SignalR 文章中&#xff0c;演示了如何通过 SignalR 实现了简单的聊天室功能&#xff1b;本着简洁就是美的原则&#xff0c;这一篇我们也来聊聊在 SignalR 中的用户和组的概念&#xff0c;理解这些基础知识有助于更好的开发基于 SignalR 的应用&#xff0c;通过对用户…

Visual Studio 2019 使用 Live Share

一.前言Visual Studio 2019 在今天发布&#xff08;北京时间&#xff09;了&#xff0c;这次带来了一个比较有趣的 Live Share 功能&#xff0c;使用它可以进行更好的协作开发。主要功能&#xff1a;更多资料可看官方介绍&#xff1a;Visual Studio 实时共享什么是Visual Studi…

cf1523B. Lord of the Values

cf1523B. Lord of the Values 题意&#xff1a; 给你一个数组&#xff0c;有n个数&#xff0c;n为偶数&#xff0c;a1&#xff0c;a2…an 现在有两个操作&#xff1a; 对于i<j 操作1&#xff1a;aiaiaj 操作2&#xff1a;ajaj-ai 把原数组转换为-a1,-a2,-a3… 题解&#…

Asp.Net Core WebAPI使用Swagger时API隐藏与分组

1、前言为什么我们要隐藏部分接口&#xff1f;因为我们在用swagger代替接口的时候&#xff0c;难免有些接口会直观的暴露出来&#xff0c;比如我们结合Consul一起使用的时候&#xff0c;会将健康检查接口以及报警通知接口暴露出来&#xff0c;这些接口有时候会出于方便考虑&…

cf1526E. Oolimry and Suffix Array(未解决)

E. Oolimry and Suffix Array 题意&#xff1a; 给定n&#xff0c;k和长度为n的后缀数组si(0<si<n-1),求长度为n的由k种字母构成的字符串种&#xff0c;后缀数组为si的有多少种 题解&#xff1a; 题解看懂了一半。。。等会了再更新 代码&#xff1a;

P2572 [SCOI2010]序列操作

P2572 [SCOI2010]序列操作 题意&#xff1a; 一个长度为n的01序列&#xff0c;下标从0开始&#xff0c;现在有五种变换操作和询问操作&#xff1a; 0 l r 把[l,r]区间内的所有数全变成01 l r 把[l,r]区间内的所有数全变成12 l r把[l,]区间内所有数全部取反3 l r询问[l,r]区间…

为您的机器配置开发环境

软件准备在本期视频中&#xff0c;我们将安装所序言的软件&#xff0c;并为我们的电脑配置.NET Core开发环境。我们需要安装如下2个软件&#xff1a;一个编辑器.NET Core SDK&#xff08;Software Development Kit&#xff09;下载并安装.NET Core 开发编辑器我的是Windows操作…

[CQOI2012] 局部极小值(状压DP + 容斥 + 搜索)

problem luogu-P3160 solution 这么小的数据范围&#xff0c;非暴力不状压。暴力 O(28!)O(28!)O(28!) 呵呵呵可以拉走了。 我们不妨从小到大填数字&#xff0c;这样如果局部极小值点还没有填的话&#xff0c;周围的九宫格就一定不能被填。 设 dp(s,i):dp(s,i):dp(s,i): 局…

基于Kubernetes 构建.NET Core 的技术体系

很多公司技术支持岗位的工作&#xff0c;如配置域名&#xff0c;部署环境&#xff0c;修改复位配置&#xff0c;服务重启&#xff0c;扩容缩容&#xff0c;梳理和完善监控&#xff0c;根据开发的需要查找日志等工作&#xff0c;需要和开发进行大量的沟通&#xff0c;如什么是外…

P4062 [Code+#1]Yazid 的新生舞会(分治做法)

P4062 [Code#1]Yazid 的新生舞会 题意&#xff1a; 给出一个序列&#xff0c;求有多少个子区间满足众数的出现次数大于区间长度的一半。 出现次数大于区间长度的一般我们称之为绝对众数 题解&#xff1a; 分治做法 对于一个区间[l,r]&#xff0c;设mid⌊lr2⌋\lfloor \frac…

[CQOI2014] 危桥(网络流)

problem luogu-P3163 solution 这是一道网络流好题&#xff0c;看的着摸不着吃不着。 初读完题&#xff0c;就知道这是一道“脱光了”的最大流。 建图基础版本&#xff1a; 建立额外源汇点。 无向边相同于两条有向边&#xff0c;直接建不影响&#xff0c;危桥流量设成 22…

那些优秀的开发者----汪宇杰:从重视细节,到成就技术专家

汪宇杰&#xff08;Edi Wang&#xff09;&#xff0c;.NET及Windows开发者&#xff0c;2018-2019年度微软最有价值专家&#xff08;Windows Development方向&#xff09;。现担任某金融科技企业的网站开发工程师。他对微软技术有鉴定的信念和不灭的热情&#xff0c;曾在Windows…

P4062 [Code+#1]Yazid 的新生舞会(线段树做法)

P4062 [Code#1]Yazid 的新生舞会&#xff08;线段树做法&#xff09; 题意&#xff1a; 给你一个序列a[1…n]​&#xff0c;求存在绝对众数的子区间个数。 绝对众数指&#xff1a;区间中出现次数最多的那个数&#xff0c;出现次数严格大于区间长度的一半。 题解&#xff1a…