传送门

题意:给一棵带边权的树,每个点开始时为白色,维护两种操作:

1.改变一个点的颜色(白变黑,黑变白)
2.询问最远的两个白点之间的距离

树分治国集论文

链分治的本质其实就是树链剖分。它们的区别是树剖维护路径询问,链分治维护全局路径。

动态点分治需要重新建一棵树,而链分治分出来的是链,本身就可以用数据结构维护。所以链分治本身就可以资瓷修改。

对于每一条链单独用数据结构维护与当前链有交集的路径信息。

对于本题,先树链剖分

记Di,Di′D_i,D_i'Di​,Di′​为节点iii沿虚边往下走到某个白点的最长和次长长度。如果不存在,记为−INF-INF−INF

用线段树维护一条链。对于一条链上的一个区间[L,R][L,R][L,R]

lmax=max{dist(L,i)+Di}lmax=max\{dist(L,i)+D_i\}lmax=max{dist(L,i)+Di​}

rmax=max{Di+dist(i,R)}rmax=max\{D_i+dist(i,R)\}rmax=max{Di​+dist(i,R)}

即:lmaxlmaxlmax表示LLL沿这条链往下走(可以不走),在[L,R][L,R][L,R]中的某个点拐出去,往下走(可以不走)到某个白点经过的最长长度。注意没有要求起点是白色。rmaxrmaxrmax同理。

再记录ansansans表示有交集的最长长度

然后用类似最大子段和的方式合并。

对于一个线段树节点ppp,左右儿子lc,rclc,rclc,rc

lmax[p]=max{lmax[lc],dist(L,mid+1)+lmax[rc]}lmax[p]=max\{lmax[lc],dist(L,mid+1)+lmax[rc]\}lmax[p]=max{lmax[lc],dist(L,mid+1)+lmax[rc]}

rmax[p]=max{rmax[lc]+dist(mid,R),rmax[rc]}rmax[p]=max\{rmax[lc]+dist(mid,R),rmax[rc]\}rmax[p]=max{rmax[lc]+dist(mid,R),rmax[rc]}

ans[p]=max{ans[lc],ans[rc],rmax[lc]+dist(mid,mid+1)+lmax[rc]}ans[p]=max\{ans[lc],ans[rc],rmax[lc]+dist(mid,mid+1)+lmax[rc]\}ans[p]=max{ans[lc],ans[rc],rmax[lc]+dist(mid,mid+1)+lmax[rc]}

边界:当L=RL=RL=R,设当前点为iii

若iii是白点

lmax=rmax=max{Di,0}lmax=rmax=max\{D_i,0\}lmax=rmax=max{Di​,0}

ans=max{0,Di,Di+Di′}ans=max\{0,D_i,D_i+D_i'\}ans=max{0,Di​,Di​+Di′​}

否则

lmax=rmax=Dilmax=rmax=D_ilmax=rmax=Di​

ans=Di+Di′ans=D_i+D_i'ans=Di​+Di′​

最后需要维护Di,Di′D_i,D_i'Di​,Di′​

当iii是白点,jjj为iii的轻儿子

Di=max{0,w(i,j)+lmax[j]}D_i=max\{0,w(i,j)+lmax[j]\}Di​=max{0,w(i,j)+lmax[j]}

当iii是黑点

Di=w(i,j)+lmax[j]D_i=w(i,j)+lmax[j]Di​=w(i,j)+lmax[j]

然后用个堆之类的瞎维护即可

然而写起来十分精神污染

有一个常用的转换方式

红色边权值为000

这样这棵树变成了二叉树,且两两之间的距离不变。也就是说和原来的树是等效的。

有什么用呢?

这样一个节点最多有一个重儿子一个轻儿子,Di′D_i'Di′​永远为−INF-INF−INF,DiD_iDi​可以直接计算,大大降低编程复杂度。当然好不好调是另外一回事

最后答案用multisetmultisetmultiset暴艹即可

复杂度O(nlogn2)O(nlog_n^2)O(nlogn2​)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <set>
#define MAXN 200005
#define INF 0x3f3f3f3f
using namespace std;
inline int read()
{int ans=0,f=1;char c=getchar();while (c<'0'||c>'9'){if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans;
}
inline char gal()
{char c=getchar();while (c<'A'||c>'Z') c=getchar();return c;
}
int n;
struct edge
{int u,v,w;
}e[MAXN];
int head[MAXN],nxt[MAXN],cnt;
void addnode(int u,int v,int w)
{e[++cnt]=(edge){u,v,w};nxt[cnt]=head[u];head[u]=cnt;
}
int son[MAXN][2];
int fa[MAXN],dep[MAXN],cost[MAXN],col[MAXN];
void dfs(int u)
{int las=u;for (int i=head[u];i;i=nxt[i])if (!dep[e[i].v]){fa[fa[e[i].v]=++n]=las;dep[e[i].v]=dep[u]+1;cost[e[i].v]=e[i].w;dfs(son[las=son[las][las!=u]=n][0]=e[i].v);}
}
int siz[MAXN],dis[MAXN],tp[MAXN],bt[MAXN];
int dfn[MAXN],pos[MAXN],tim;
void Dfs(int u)
{if (!u) return;siz[u]=1;Dfs(son[u][0]),Dfs(son[u][1]);siz[u]+=siz[son[u][0]]+siz[son[u][1]];if (siz[son[u][0]]<siz[son[u][1]]) swap(son[u][0],son[u][1]);
}
multiset<int> re;
int rt[MAXN],tot;
int ch[MAXN<<2][2],lmax[MAXN<<2],rmax[MAXN<<2],ans[MAXN<<2];
inline int d(const int& x)
{if (!son[x][1]) return col[x]? 0:-INF;if (col[x]) return max(cost[son[x][1]]+lmax[rt[son[x][1]]],0);return cost[son[x][1]]+lmax[rt[son[x][1]]];
}
#define lc ch[p][0]
#define rc ch[p][1]
inline void update(const int& p,const int& l,const int& r)
{int mid=(l+r)>>1;lmax[p]=max(lmax[lc],dis[pos[mid+1]]-dis[pos[l]]+lmax[rc]);rmax[p]=max(rmax[lc]+dis[pos[r]]-dis[pos[mid]],rmax[rc]);ans[p]=max(max(ans[lc],ans[rc]),rmax[lc]+cost[pos[mid+1]]+lmax[rc]);
}
void build(int& p,int l,int r)
{p=++tot;if (l==r){if (col[pos[l]]) ans[p]=lmax[p]=rmax[p]=max(0,d(pos[l]));else lmax[p]=rmax[p]=d(pos[l]),ans[p]=-INF;return;}int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);update(p,l,r);
}
void modify(int p,int l,int r,int k)
{if (l==r){if (col[pos[l]]) ans[p]=lmax[p]=rmax[p]=max(0,d(pos[l]));else lmax[p]=rmax[p]=d(pos[l]),ans[p]=-INF;return;}int mid=(l+r)>>1;if (k<=mid) modify(lc,l,mid,k);else modify(rc,mid+1,r,k);update(p,l,r);
}
void DFS(int u,int t)
{if (!u) return;dis[u]=dis[fa[u]]+cost[u];bt[tp[u]=t]=pos[dfn[u]=++tim]=u;DFS(son[u][0],t);DFS(son[u][1],son[u][1]);if (u==t) build(rt[u],dfn[u],dfn[bt[u]]),re.insert(ans[rt[u]]);
}
int main()
{freopen("test.in","r",stdin);n=read();int cnt=n;for (int i=1;i<=n;i++) col[i]=1;for (int i=1;i<n;i++){int u,v,w;u=read(),v=read(),w=read();addnode(u,v,w),addnode(v,u,w);}dep[1]=1;dfs(1);Dfs(1);DFS(1,1);for (int i=read();i;--i){if (gal()=='A') cnt? printf("%d\n",max(0,*re.rbegin())):puts("They have disappeared.");else{int x=read();for ((col[x]^=1)? ++cnt:--cnt;x;re.erase(re.find(ans[rt[tp[x]]])),modify(rt[tp[x]],dfn[tp[x]],dfn[bt[tp[x]]],dfn[x]),re.insert(ans[rt[tp[x]]]),x=fa[tp[x]]);}}return 0;
}

做这种题一定要先理清思路,弄懂定义再开始码,不要边想边写

【SPOJ2666】QTree4【链分治】相关推荐

  1. 洛谷 4115 Qtree4——链分治

    题目:https://www.luogu.org/problemnew/show/P4115 论文:https://wenku.baidu.com/view/1bc2e4ea172ded630b1cb ...

  2. bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...

  3. [BJWC2018]Border 的四种求法(后缀自动机+链分治+线段树合并)

    题目描述 给一个小写字母字符串 S ,q 次询问每次给出 l,r ,求 s[l..r] 的 Border . Border: 对于给定的串 s ,最大的 i 使得 s[1..i] = s[|s|-i+ ...

  4. 【THUSC2018】史莱姆之友【长链剖分】【链分治NTT】

    不知道这题能不能发出来,如果不能请联系我,我什么都会做的 题意:给一棵 nnn 个结点的树,每个结点有个 ax+bax+bax+b,求所有根到叶子的乘积之和.系数模 99824435399824435 ...

  5. 【CF 600E】Lomsat gelral(树上启发式合并, dsu on tree, 静态链分治,模板题)

    Algorithm 名称:树上启发式合并, dsu on tree, 静态链分治 用处:一般用来解决一类不带修改的子树查询问题 核心思想为:利用重链剖分的性质优化子树贡献的计算. 前置知识:启发式合并 ...

  6. 【ZJOI2007】捉迷藏(链分治)

    传送门 闲着无聊打算用链分治写一遍,结果因为脑瓜子不好用调了两个多小时... 其实是第一次自己打链分治 用 setsetset 维护轻儿子向下的最长链 考虑最后的路径一定经过某一条重链(或是一个点) ...

  7. BZOJ 4732 UOJ #268 [清华集训2016]数据交互 (树链剖分、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...

  8. UOJ #268 BZOJ 4732 [清华集训2016]数据交互 (树链剖分、线段树)

    题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=4732 (UOJ) http://uoj.ac/problem/268 题解 ...

  9. 【CTSC2010】珠宝商(SAM)(点分治)(根号分治)

    传送门 给你一棵树,树上每个点有字符,询问所有树上路径形成的字符串在给定模式串中一共出现了几次.在模式串中不同位置出现要多次计算. 题解: 好题啊. 树上路径统计类的问题显然考虑的一般就是链分治和点分 ...

最新文章

  1. case when then else end
  2. ECharts的简单使用过程
  3. 论文阅读:Learnable pooling with Context Gating for video classification
  4. 一个三行两列右列固定左列自适应宽度的CSS
  5. Excel图表横坐标设置怎么做?(亲测)
  6. [译]试用新的System.Text.Json API
  7. java控制单元测试_java – 当单元测试控制器时,模拟一个Spring Validator
  8. 关于public class 类名{ public static void main(String[] args)}的一些说明
  9. 如何使用Service的Context弹出Dialog对话框,即全局性对话框
  10. 重磅 | 阿里云启动AliSQL邀测,性能比MySQL提升70%,秒杀场景提升百倍
  11. 计算机基础知识思维导图怎么画,怎样在计算机中绘制思维导图的操作过程分享...
  12. VBA变量和函数名中文拼音输入提示
  13. 记一次简单的企业微信推送消息开发(第三方应用开发)
  14. python爬虫之爬取微信公众号文章中的图片
  15. 靠写代码登上胡润富豪榜花半年写得Python基础 入门必看
  16. 化工学matlab,化工和石化行业
  17. Vue项目安装XLSX成功后,生成项目报错:“export ‘default‘ (imported as ‘XLSX‘) was not found in ‘xlsx‘
  18. 自建服务器系列-0元搭建linux服务器(windows笔记本)
  19. 滴滴夜莺:从监控告警系统向运维平台演化
  20. 如何把一组计算机做成云,旧电脑如何变成云电脑?进来了解下云电脑

热门文章

  1. 拿了年终奖后,发现自己又拖后腿了?对不起,可能事实并没有那么糟糕...
  2. 被学校辞退、拒绝FB后:语音识别大牛Povey确认兼职北京初创公司,称主业还选中国...
  3. TensorFlow的这些骚操作你都知道吗?
  4. 120天的烧脑只为孩子设计一套教具~
  5. Lanchester战争模型:用可分离变量的微分方程占卜战事
  6. 《SAS编程与数据挖掘商业案例》学习笔记之八
  7. Java类集-set
  8. 启动ipython内核发生错误_ipython3启动
  9. 绘制矩形php,PHP_php绘制一个矩形的方法,本文实例讲述了php绘制一个矩 - phpStudy...
  10. 面试字节我被String类的问题给问死了!