Jamie and Tree[CF916E]

Jamie and Tree[CF916E]

题意:

有一棵n个点的树,每个节点上有一个权值wi,最开始根为1号点.现在有3种
类型的操作:
• 1 root, 表示将根设为root.
• 2 u v x, 设u, v的最近公共祖先为p, 将p的子树中的所有点的权值加上x.
• 3 u, 查询u的子树中的所有点的权值和.
对于每个3操作,输出答案.

题解:

须知知识:线段树,树链剖分

  1. 如果真的换根太麻烦了,所以我们每次只记录新根,并看看新根在后续操作中会有什么影响
  2. 如果在没有换根的情况下,操作2很容易实现,但是因为现在root已经发生改变所以我们需要特判。
    lca1=lca(u,v)
    lca2=lca(root,v)
    lca3=lca(root,u)
    lca=max(dep[lca1],dep[lca2],dep[lca3])
    我们要先记录lca1,lca2,lca3中dep最深的
    如果root不在lca的子树里,那直接在区间[l[lca],r[lca]]内更新x即可
    如果root等于lca,那么就是全树更新
    如果root在lca的子树上,先把整个树更新,然后找到root到lca的路径与lca的儿子节点,更新子树-x
    相当于先全部+x,然后将不需要修改的部分再-x
if(root==lca1)tree.update(1,1,n,1,n,x);else if(dfn[rt]<dfn[lca1]||dfn[rt]>dfn[lca1]+size[lca1]-1)tree.update(1,1,n,dfn[lca1],dfn[lca1]+size[lca1]-1,x);else {lca1=change(lca1);tree.update(1,1,n,1,n,x);tree.update(1,1,x,dfn[lca1],dfn[lca1]+size[lca1]-1,-x);}
  1. 对于操作三,我们要判断root与v的关系,如果root不在v的子树上,那就正常操作sum(l[v],r[v])
    如果root就是v,更新整个子树
    但如果root在v的子树上,那么其实和操作2的第三个情况类似,先求所以树的权值,然后减去不需要算的部分。这里不需要算的部分是root到lca的路径与lca的儿子节点X
    (为什么是这个点?看着图仔细想想)
    在这里插入图片描述
if(u==rt)sum=tree.query(1,1,n,1,n);
else if(dfn[rt]<dfn[u]||dfn[rt]>dfn[u]+size[u]-1)sum=tree.query(1,1,n,dfn[u],dfn[u]+size[u]-1);
else {u=change(u);sum+=tree.query(1,1,n,1,n);sum-=tree.query(1,1,n,dfn[u],dfn[u]+size[u]-1);}

代码:

#include<bits/stdc++.h>#define REP(i,a,b) for(int i=a;i<=b;++i)
typedef long long ll;
using namespace std;template<typename T>void read(T &x){T _=0,mul=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')mul=-1;ch=getchar();}while(isdigit(ch))_=(_<<1)+(_<<3)+(ch^'0'),ch=getchar();x=_*mul;
}const int maxn=3e5+10;struct Segment_Tree{
#define mid ((l+r)>>1)
#define lc (rt<<1)
#define rc (rt<<1|1)
#define lson lc,l,mid
#define rson rc,mid+1,rll sum[maxn<<2],tag[maxn<<2];void pushdown(int rt,int l,int r){sum[lc]+=tag[rt]*(mid-l+1);tag[lc]+=tag[rt];sum[rc]+=tag[rt]*(r-mid);  tag[rc]+=tag[rt];tag[rt]=0;}void update(int rt,int l,int r,int L,int R,ll x){if(L<=l && r<=R){sum[rt]+=(r-l+1)*x;tag[rt]+=x;return;}if(tag[rt])pushdown(rt,l,r);if(L<=mid)update(lson,L,R,x);if(R>=mid+1)update(rson,L,R,x);sum[rt]=sum[lc]+sum[rc];}ll query(int rt,int l,int r,int L,int R){if(L<=l && r<=R)return sum[rt];ll ret=0ll;if(tag[rt])pushdown(rt,l,r);if(L<=mid)ret+=query(lson,L,R);if(R>=mid+1)ret+=query(rson,L,R);return ret;}
}T;int n,q,root,w[maxn],cnt;
int to[maxn<<1],last[maxn<<1],beg[maxn],cnte;
int fa[maxn],son[maxn],top[maxn],siz[maxn],dep[maxn],cnt_dfn,dfn[maxn];void add(int u,int v){last[++cnte]=beg[u];beg[u]=cnte;to[cnte]=v;
}void dfs1(int u,int f){fa[u]=f;siz[u]=1;dep[u]=dep[f]+1;for(int i=beg[u];i;i=last[i]){if(to[i]==f)continue;dfs1(to[i],u);siz[u]+=siz[to[i]];if(siz[to[i]]>siz[son[u]])son[u]=to[i];}
}void dfs2(int u,int t){dfn[u]=++cnt_dfn;top[u]=t;if(son[u])dfs2(son[u],t);for(int i=beg[u];i;i=last[i]){if(to[i]==fa[u] || to[i]==son[u])continue;dfs2(to[i],to[i]);}
}int find(int u,int v){while(top[u]!=top[v]){++cnt;if(dep[top[u]]<dep[top[v]])swap(u,v);u=fa[top[u]];}return dep[u]<dep[v] ? u : v;
}int change(int u){int v=root;while(top[v]!=top[u]){if(fa[top[v]]==u)return top[v];v=fa[top[v]];}return son[u];
}void init(){read(n); read(q);root=1;REP(i,1,n)read(w[i]);REP(i,1,n-1){int u,v;read(u); read(v);add(u,v);add(v,u);}dfs1(1,0);dfs2(1,1);REP(i,1,n)T.update(1,1,n,dfn[i],dfn[i],w[i]);
}int main(){init();REP(i,1,q){int ty,u,v;ll x;read(ty);if(ty==1){read(u);root=u;}else if(ty==2){read(u); read(v); read(x);int lca=find(u,v),tmp;if(dep[tmp=find(u,root)]>dep[lca])lca=tmp;if(dep[tmp=find(v,root)]>dep[lca])lca=tmp;if(lca==root)T.update(1,1,n,1,n,x);else if(dfn[root]<dfn[lca] || dfn[root]>dfn[lca]+siz[lca]-1)T.update(1,1,n,dfn[lca],dfn[lca]+siz[lca]-1,x);else{lca=change(lca);T.update(1,1,n,1,n,x);T.update(1,1,n,dfn[lca],dfn[lca]+siz[lca]-1,-x);}}else{ll sum=0ll;read(u);if(u==root)sum=T.query(1,1,n,1,n);else if(dfn[root]<dfn[u] || dfn[root]>dfn[u]+siz[u]-1)sum=T.query(1,1,n,dfn[u],dfn[u]+siz[u]-1);else{u=change(u);sum+=T.query(1,1,n,1,n);sum-=T.query(1,1,n,dfn[u],dfn[u]+siz[u]-1);}cout<<sum<<endl;}}return 0;
}

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

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

相关文章

领域驱动设计,让程序员心中有码(三)

“正如西方古典哲学在现代社会逐渐式微&#xff0c;成为少数内心丰满者们填充自己精神世界的宝贵食物&#xff0c;UML也这样&#xff1b;互联网技术飞速发展的今天&#xff0c;各类软件设计思想层出不穷&#xff0c;正是站在UML和其他各种软件基础理论巨人的肩膀上&#xff0c;…

Tavan

Tavan–简单的k进制题 呵呵真的简单 也就是考试没做出来罢了&#xff0c;不慌不慌&#xff0c;奶我一口&#xff0c;还能活 【题目摘要】 题目描述 小 Zeljko 一直在阁楼里读他奶奶的旧信&#xff0c;并且发现了一个长度为 N 的单词。 不幸的是&#xff0c;由于溢出的墨水&…

.NET Core 2.x中使用Named Options处理多个强类型配置实例

来源&#xff1a; Using multiple instances of strongly-typed settings with named options in .NET Core 2.x作者&#xff1a; Andrew Lock译者&#xff1a; Lamond Lu.NET Core从1.0版本开始&#xff0c;就已经开始使用Options模式绑定强类型配置对象。从那时起到现在&…

YBTOJ:魔法数字(数位dp)

文章目录题目描述解析题目描述 解析 迷惑。。。 首先&#xff0c;比较容易想到用二进制状态压缩记录1-9是否在十进制中出现过 然后就是整除的问题 如果记录余数&#xff0c;它的模数又有9个 开九维余数直接爆炸。。。 怎么办嘞&#xff1f; 有一个结论&#xff1a; 若&#xf…

Prosjecni(构造)

Prosjecni 【题目摘要】 描述 Slavko很无聊&#xff0c;所以他把正整数填到N*N的方阵中。 如果他填出来的方阵满足以下条件&#xff0c;他会特别高兴&#xff1a; ●每行中的数字的平均值是一个位于同一行的整数。 ●每列中的数字的平均值是一个位于同一列的整数。 ●表中的所…

撒花!中文翻译仓库链接已加入 ML.NET 官方示例网站首页

从2018年12月02日决定开始做ML.NET 示例中文版https://github.com/feiyun0112/machinelearning-samples.zh-cn&#xff0c;然后以每天一篇的速度进行翻译&#xff0c;总共耗时15天&#xff0c;将现有的官方实例全部翻译成了中文&#xff0c;并提交了添加中文链接PR&#xff0c;…

P3803 【模板】多项式乘法(FFT)

P3803 【模板】多项式乘法&#xff08;FFT&#xff09; 题目描述 给定一个 n 次多项式 F(x)&#xff0c;和一个 m 次多项式 G(x)。 请求出 F(x)和 G(x)的卷积。 从低到高输出F(x)*G(x)的系数 另一种问法&#xff1a; 如果有两个无限序列a和b&#xff0c;那么它们卷积的结果是…

YBTOJ:单词频率(AC自动机)

解析 我对力量一无所知 通过这题&#xff0c;可以看出我对AC自动机还是完全没有理解 qwq 首先容易想到&#xff1a; 建一课trie树&#xff0c;然后建树时记录每个串s的终点&#xff0c;这个点后面每被经过一次&#xff0c;就相当于出现一次该单词s 但是&#xff0c;这种“出现”…

一元一次方程

一元一次方程–逆波兰栈 【题目摘要】 题目描述 SLON是一个调皮的学生&#xff0c;为了让他静下心来&#xff0c;老师给他出了一道数学题&#xff1a; 给定表达式A&#xff0c;A中含有变量x和,-,*,(,)这些符号&#xff0c;括号成对出现&#xff0c;一个算术运算符均对应两个操…

.net core上 K8S(七).netcore程序的服务发现

正文上一章我们分享了k8s的网络代理模式&#xff0c;今天我们来分享一下k8s中的服务发现。1.环境变量模式的服务发现k8s默认为我们提供了通过环境变量来实现服务发现的功能&#xff0c;前提是1.需要service在pod之前创建2.适用于同一命名空间1.1创建servicekubectl create -f n…

ASP.NET Core 实战:使用ASP.NET Core Web API 和 Vue.js 搭建前后端分离项目

一、前言这几年前端的发展速度就像坐上了火箭&#xff0c;各种的框架一个接一个的出现&#xff0c;需要学习的东西越来越多&#xff0c;分工也越来越细&#xff0c;作为一个 .NET Web 程序猿&#xff0c;多了解了解行业的发展&#xff0c;让自己扩展出新的技能树&#xff0c;对…

【CF1199 D,E, F】Welfare State // Matching vs Independent Set // Rectangle Painting 1

2019-08-15下午三道练习题CF1199 思路有点难想 but很好实现 这是原网站链接&#xff1a;传送门 这里只完成D, E, F三题 文章目录D&#xff1a;Welfare State题目大意正解瞅瞅代码E:Matching vs Independent Set题目大意正解代码实现F:Rectangle Painting 1题目大意正解代码实现…

YBTOJ:前缀匹配(AC自动机)

文章目录题目描述解析代码题目描述 解析 做的不错 把trie树真的当成一棵树递归即可 注意一个标记时的问题&#xff1a; void AC(){int lstrlen(s01),pl1;for(int i1;i<l;i){int aask(s0[i]);pltr[pl][a];int kpl;while(k>1){if(ok[k]) break;//注意&#xff01;ok[k]1;…

[HAOI2006]均分数据

[HAOI2006]均分数据 题解&#xff1a; 题目稍微解释一下&#xff1a; 把n个数以分为m组&#xff0c;计算每一组的和&#xff0c;求得到的这m个数的方差。由于分法是任意的&#xff0c;我们要求这些方差中的最小值 我们先用STL中的函数random_shuffle()用来对一个元素序列进行…

Docker最全教程——从理论到实战(八)

在本系列教程中&#xff0c;笔者希望将必要的知识点围绕理论、流程&#xff08;工作流程&#xff09;、方法、实践来进行讲解&#xff0c;而不是单纯的为讲解知识点而进行讲解。也就是说&#xff0c;笔者希望能够让大家将理论、知识、思想和指导应用到工作的实际场景和实践之中…

不定方程(质数与因数)

文章目录题目描述解析代码题目描述 数据范围有误&#xff01;应该是不超过1e6 解析 容易推出&#xff1a; y&#xff08;x∗*∗n!)/(x-n!) 换元&#xff0c;令tx-n&#xff01; 则&#xff1a; yn!(n!)2/t 因为x、y都与t一一对应 所以本题就是求 (n!)2 的因数个数 我们求出n&…

Matlab快速入门

命令行窗口 clc 清屏 clear 清理变量 常用矩阵&#xff1a; x[0:2] 这是转置符号xlinspace(0,2,5) 从0到2分配5个空间xzeros(2,3)两行三列全为0的矩阵、 ones(2)2行2列全为1的方阵 eye(2)单位阵 rand(1,2)产生一行二列的随机数&#xff08;从0到1之间均匀随机数&#xff09;固…

【CF 1191】Tokitsukaze, CSL and Stone Game//Tokitsukaze and Duel//Tokitsukaze and Strange Rectangle

很难想 but很好实现 博弈论专练 传送门 惯例这里只完成D&#xff0c;E&#xff0c;F 话不多说上代码 文章目录D:Tokitsukaze, CSL and Stone Game题目大意题解代码实现E&#xff1a;Tokitsukaze and Duel题目大意题解代码实现E:Tokitsukaze and Strange Rectangle题目大意题解代…

【.NET Core项目实战-统一认证平台】第十一章 授权篇-密码授权模式

上篇文章介绍了基于Ids4客户端授权的原理及如何实现自定义的客户端授权&#xff0c;并配合网关实现了统一的授权异常返回值和权限配置等相关功能&#xff0c;本篇将介绍密码授权模式&#xff0c;从使用场景、源码剖析到具体实现详细讲解密码授权模式的相关应用。.netcore项目实…

YBTOJ:灯光控制(贪心)(公倍数)(暴力枚举)

文章目录题目描述解析代码题目描述 解析 没有想出来 首先可以确定开关要么开一次&#xff0c;要么不动&#xff0c;其他都和这俩是等价的 一开始最先想到的就是贪心的方法&#xff0c;每个开关遍历&#xff0c;如果按下会使答案变好就按下。 但是显然当前的开闭对后面是有后效…