「模板」 树链剖分 HLD
「模板」 树链剖分 HLD
不懂OOP的OIer乱用OOP出人命了。
谨此纪念人生第一次类套类。
以及第一次OI相关代码打过200行。
#include <algorithm>
#include <cstdio>
#include <cstring>
using std::swap;
const int MAXN=100010,MAXM=200010;
int n,m,rt,P;
class HLD
{
public:
HLD(void)
{
num=cnt=0;
memset(vis,0,sizeof vis);
memset(head,0,sizeof head);
memset(p,0,sizeof p);
}
void Init(void)
{
for(int i=1;i<=n;++i)
scanf("%d",&p[i].v);
for(int i=1,x,y;i<n;++i)
{
scanf("%d %d",&x,&y);
AddEdges(x,y);
}
DFS1(rt,1),DFS2(rt,rt),T.Build(this,1,1,n);
}
void AddPath(int x,int y,int v)
{
int a,b;
while((a=p[x].top)^(b=p[y].top))
p[a].d>p[b].d ? (T.Add(1,p[a].DFN,p[x].DFN,v),x=p[a].ft) : (T.Add(1,p[b].DFN,p[y].DFN,v),y=p[b].ft);
if(p[x].d>p[y].d)
swap(x,y);
T.Add(1,p[x].DFN,p[y].DFN,v);
}
int SumPath(int x,int y)
{
int a,b,ans=0;
while((a=p[x].top)^(b=p[y].top))
p[a].d>p[b].d ? (ans+=T.Sum(1,p[a].DFN,p[x].DFN),x=p[a].ft) : (ans+=T.Sum(1,p[b].DFN,p[y].DFN),y=p[b].ft);
if(p[x].d>p[y].d)
swap(x,y);
return (ans+T.Sum(1,p[x].DFN,p[y].DFN))%P;
}
void AddSubtree(int x,int v)
{
T.Add(1,p[x].DFN,p[x].DFN+p[x].size-1,v);
}
int SumSubtree(int x)
{
return T.Sum(1,p[x].DFN,p[x].DFN+p[x].size-1);
}
private:
bool vis[MAXN];
int cnt,num,head[MAXN],rank[MAXN];
struct node
{
int v,d,ft,son,size,top,DFN;
}p[MAXN];
struct edge
{
int nxt,to;
edge(int _nxt=0,int _to=0)
{
nxt=_nxt,to=_to;
}
}e[MAXM];
class SegmentTree
{
public:
void Build(HLD *qwq,int i,int l,int r)
{
s[i]=node(l,r,0);
if(l==r)
{
s[i].v=qwq->p[qwq->rank[l]].v;
return;
}
int j=i<<1,mid=l+r>>1;
Build(qwq,j,l,mid),Build(qwq,j|1,mid+1,r);
PushUp(i);
}
void Add(int i,int l,int r,int v)
{
if(l==s[i].l && r==s[i].r)
{
Update(i,v);
return;
}
if(s[i].l^s[i].r && s[i].lazy)
PushDown(i);
int j=i<<1,mid=s[i].l+s[i].r>>1;
if(r<=mid)
Add(j,l,r,v);
else if(l>mid)
Add(j|1,l,r,v);
else
Add(j,l,mid,v),Add(j|1,mid+1,r,v);
PushUp(i);
}
int Sum(int i,int l,int r)
{
if(l==s[i].l && r==s[i].r)
return s[i].v;
if(s[i].l^s[i].r && s[i].lazy)
PushDown(i);
int j=i<<1,mid=s[i].l+s[i].r>>1;
if(r<=mid)
return Sum(j,l,r);
else if(l>mid)
return Sum(j|1,l,r);
else
return (Sum(j,l,mid)+Sum(j|1,mid+1,r))%P;
}
private:
struct node
{
int l,r,v,lazy;
node(int _l=0,int _r=0,int _lazy=0)
{
l=_l,r=_r,lazy=_lazy;
}
}s[MAXN<<2];
void Update(int i,int v)
{
s[i].v=(s[i].v+v*(s[i].r-s[i].l+1))%P;
s[i].lazy=(s[i].lazy+v)%P;
}
void PushUp(int i)
{
int j=i<<1;
s[i].v=(s[j].v+s[j|1].v)%P;
}
void PushDown(int i)
{
int j=i<<1;
Update(j,s[i].lazy),Update(j|1,s[i].lazy);
s[i].lazy=0;
}
}T;
void AddEdge(int u,int v)
{
e[++cnt]=edge(head[u],v);
head[u]=cnt;
}
void AddEdges(int u,int v)
{
AddEdge(u,v),AddEdge(v,u);
}
void DFS1(int u,int k)
{
p[u].d=k,p[u].size=1;
for(int i=head[u],v;i;i=e[i].nxt)
if(!p[v=e[i].to].size)
{
DFS1(v,k+1);
p[v].ft=u,p[u].size+=p[v].size;
if(p[v].size>p[p[u].son].size)
p[u].son=v;
}
}
void DFS2(int u,int top)
{
p[u].top=top,vis[u]=1;
p[u].DFN=++num,rank[num]=u;
if(p[u].son)
DFS2(p[u].son,top);
for(int i=head[u],v;i;i=e[i].nxt)
if(!vis[v=e[i].to])
DFS2(v,v);
}
}HLT;
int main(int argc,char *argv[])
{
scanf("%d %d %d %d",&n,&m,&rt,&P);
HLT.Init();
for(int i=1,opt,x,y,z;i<=m;++i)
{
scanf("%d %d",&opt,&x);
switch(opt)
{
case 1:
scanf("%d %d",&y,&z);
HLT.AddPath(x,y,z);
break;
case 2:
scanf("%d",&y);
printf("%d\n",HLT.SumPath(x,y));
break;
case 3:
scanf("%d",&z);
HLT.AddSubtree(x,z);
break;
case 4:
printf("%d\n",HLT.SumSubtree(x));
break;
}
}
return 0;
}
谢谢阅读。
「模板」 树链剖分 HLD的更多相关文章
- P3384 【模板】树链剖分
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- luogu3384 【模板】树链剖分
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 【算法学习】【洛谷】树链剖分 & P3384 【模板】树链剖分 P2146 软件包管理器
刚学的好玩算法,AC2题,非常开心. 其实很早就有教过,以前以为很难就没有学,现在发现其实很简单也很有用. 更重要的是我很好调试,两题都是几乎一遍过的. 介绍树链剖分前,先确保已经学会以下基本技巧: ...
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- 树链剖分 - Luogu 3384【模板】树链剖分
[模板]树链剖分 题目描述 已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操 ...
- 洛谷p3384【模板】树链剖分题解
洛谷p3384 [模板]树链剖分错误记录 首先感谢\(lfd\)在课上调了出来\(Orz\) \(1\).以后少写全局变量 \(2\).线段树递归的时候最好把左右区间一起传 \(3\).写\(dfs\ ...
- 洛谷 P3384 【模板】树链剖分
树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...
- Luogu 3384 【模板】树链剖分
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- Luogu P3384 【【模板】树链剖分】
转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...
随机推荐
- Alpha发布文案加美工展示
目录 团队简介 项目进展 组内分工 队员总结 后期计划 一.团队简介 二.项目进展 从选题发布到今天的Alpha发布,我们团队经历了许许多多的磨难.我们最终设计了如下的功能:首页.班级.个人.更多.打 ...
- Thunder团队——文案+美工
团队名称:Thunder 组长:王航 成员:李传康.代秋彤.邹双黛.苗威.宋雨.胡佑蓉.杨梓瑞 项目名称:爱阅app 需求概述: 现在市面上有很多手机阅读器,但是基本上不是收费就是广告满天飞.基于这种 ...
- eg_4
4. 编写一个程序,要求以树状结构展现特定的文件夹及其子文件(夹) import java.io.*; public class Test { public static void main(Stri ...
- iOS-addSubView时给UIView添加效果
CAKeyframeAnimation* animation = [CAKeyframeAnimation animationWithKeyPath:@"transform"]; ...
- C# Winform防止闪频和再次运行
其实想实现只允许运行一个实例很简单,就是从program的入口函数入手.有两种情况: 第一种,用户运行第二个的时候给一个提示: using System; using System.Collectio ...
- PAT 甲级 1012 The Best Rank
https://pintia.cn/problem-sets/994805342720868352/problems/994805502658068480 To evaluate the perfor ...
- node必学的Hello World实现--服务器实现
node是JavaScript运行在后端的一种实现.而后端语言,不管是php,java都需要一个服务器才能跑起来,node如是. node的服务器较php而言,少了单独安装服务器的步骤,node的服务 ...
- 面试中常用排序算法的python实现和性能分析
这篇是关于排序的,把常见的排序算法和面试中经常提到的一些问题整理了一下.这里面大概有3个需要提到的问题: 虽然专业是数学,但是自己还是比较讨厌繁琐的公式,所以基本上文章所有的逻辑,我都尽可能的用大白话 ...
- 抓取进程中包括其所有线程的iowait时间
perf事件是可以按照线程按照进程统计的呢,但是/proc/接口就不提供这样的功能 hon@station6:/proc/6288$ sudo perf stat -e sched:sched_swi ...
- P1315 观光公交
题目描述 风景迷人的小城Y 市,拥有n 个美丽的景点.由于慕名而来的游客越来越多,Y 市特意安排了一辆观光公交车,为游客提供更便捷的交通服务.观光公交车在第 0 分钟出现在 1号景点,随后依次前往 2 ...