看到换根果断lct啊,然而其实我板子还没有打熟,还不会维护子树信息,于是就挂掉了……

然而正解并不是lct。

其实好像很久很久以前将lca的时候好像讲到过一道换根的题,当时没有听懂。

直接说正解吧:

把dfs序搞出来用线段树维护。

用一个变量记录当前根节点,操作一直接改就行了。

然后是操作三:

分情况讨论,设当前根节点为root,询问的点为a。

如果root不在a的子树内,那么root不会影响a的子树,仍然输出1为根时的子树和就行了。

如果在子树内,

如图,如果要查询1的子树和,那么找到1与root这条链上靠近1的点,整体的和减去这个点的子树和就是了。(感性理解一下。)

那么这个点怎么求呢?只需要对于每个点把与他直接相连的儿子的dfs序塞到一个vector里,upper_bound然后-1就可以了。

操作二:

首先求出以1为根是a,b两点的lca。

与操作三类似,如果root不在lca的子树内,那么root不会影响lca,直接加就行。

如果在子树内,那么找a,b与root的lca中深度较大的那个。

之后就和操作三一样了。

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define LL long long
#define re register
#define co const
#define rec re co
#define inline __attribute((always_inline))
const int LLL=<<|;
char buffer[LLL],*S,*TT;
#define getchar() ((S==TT&&(TT=(S=buffer)+fread(buffer,1,LLL,stdin),S==TT))?EOF:*S++)
using namespace std;
struct edge
{
int u,v,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define n(x) ed[x].nxt
}ed[];
int first[],num_e;
#define f(x) first[x]
int n,q,w[];
bool pd2=,pd3=;
vector<int> inc[];
LL fa[][],dep[];
int dfn[],id[],cnt,L[],R[];LL res;
int siz[],son[],top[];
void dfs1(int x)
{
siz[x]=;
for(int i=f(x);i;i=n(i))
if(v(i)!=fa[x][])
{
fa[v(i)][]=x;dep[v(i)]=dep[x]+;
dfs1(v(i));siz[x]+=siz[v(i)];
if(siz[v(i)]>siz[son[x]])son[x]=v(i);
}
}
void dfs2(int x,int t)
{
top[x]=t;dfn[x]=++cnt;id[cnt]=x;L[x]=cnt;
if(son[x])dfs2(son[x],t),inc[x].push_back(dfn[son[x]]);
for(int i=f(x);i;i=n(i))
if(v(i)!=fa[x][]&&v(i)!=son[x])
dfs2(v(i),v(i)),inc[x].push_back(dfn[v(i)]);
R[x]=cnt;
}
inline int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])swap(x,y);
y=fa[top[y]][];
}
if(dep[x]>dep[y])swap(x,y);
return x;
}
struct xjs_Tree
{
struct tree
{
int l,r;LL sum,la;
#define l(x) tr[x].l
#define r(x) tr[x].r
#define la(x) tr[x].la
#define sum(x) tr[x].sum
#define ls(x) ((x)<<1)
#define rs(x) (ls(x)+1)
}tr[];
void build(rec int x,rec int l,rec int r)
{
l(x)=l,r(x)=r,la(x)=;
if(l==r){sum(x)=w[id[l]];return;}
int mid=(l+r)>>;
build(ls(x),l,mid);
build(rs(x),mid+,r);
sum(x)=sum(ls(x))+sum(rs(x));
}
inline void down(rec int x)
{
if(l(x)==r(x))return;
if(!la(x))return;
sum(ls(x))+=(r(ls(x))-l(ls(x))+)*la(x);
sum(rs(x))+=(r(rs(x))-l(rs(x))+)*la(x);
la(ls(x))+=la(x);la(rs(x))+=la(x);la(x)=;
}
void add(rec int x,rec int l,rec int r,rec LL y)
{
if(l>r)return;
down(x);
if(l(x)>=l&&r(x)<=r)
{
sum(x)+=(r(x)-l(x)+)*y;
la(x)+=y;return;
}
int mid=(l(x)+r(x))>>;
if(l<=mid)add(ls(x),l,r,y);
if(r> mid)add(rs(x),l,r,y);
sum(x)=sum(ls(x))+sum(rs(x));
}
LL ask(rec int x,rec int l,rec int r)
{
if(l>r)return ;
down(x);
if(l(x)>=l&&r(x)<=r)return sum(x);
int mid=(l(x)+r(x))>>;LL ans=;
if(l<=mid)ans+=ask(ls(x),l,r);
if(r> mid)ans+=ask(rs(x),l,r);
return ans;
}
}T;
inline int read();
inline void add(rec int u,rec int v);
signed main()
{
// freopen("S1_1.in","r",stdin);
// freopen("in.txt","r",stdin);
// freopen("1.out","w",stdout); n=read(),q=read();int tu,tv;
for(re int i=;i<=n;i++)w[i]=read();
for(re int i=;i<n;i++)tu=read(),tv=read(),add(tu,tv),add(tv,tu);
re int root=;
dep[]=;dfs1(),dfs2(,);T.build(,,n);
re int opt,a,b,c;
for(re int i=;i<=q;i++)
{
opt=read();
if(opt==)a=read(),root=a;
if(opt==)
{
a=read(),b=read(),c=read();
int lca=LCA(a,b);
if(lca==root)T.add(,,n,c);
else if(dfn[root]<L[lca]||dfn[root]>R[lca])T.add(,L[lca],R[lca],c);
else
{
int t1=LCA(a,root),t2=LCA(b,root);
if(dep[t1]>dep[t2])lca=t1;
else lca=t2;
if(lca==root)T.add(,,n,c);
else if(dfn[root]<L[lca]||dfn[root]>R[lca])T.add(,L[lca],R[lca],c);
else
{
int te=upper_bound(inc[lca].begin(),inc[lca].end(),dfn[root])-inc[lca].begin()-;
lca=inc[lca][te];lca=id[lca];
T.add(,,L[lca]-,c),T.add(,R[lca]+,n,c);
}
}
}
if(opt==)
{
a=read();
if(a==root)printf("%lld\n",T.ask(,,n));
else if(dfn[root]<L[a]||dfn[root]>R[a])printf("%lld\n",T.ask(,L[a],R[a]));
else
{
int te=upper_bound(inc[a].begin(),inc[a].end(),dfn[root])-inc[a].begin()-;
te=inc[a][te];te=id[te];
printf("%lld\n",T.ask(,,L[te]-)+T.ask(,R[te]+,n));
}
}
}
return ;
}
inline int read()
{
int s=,f=;char a=getchar();
while(a<''||a>''){if(a=='-')f=-;a=getchar();}
while(a>=''&&a<=''){s=s*+a-'';a=getchar();}
return s*f;
}
inline void add(rec int u,rec int v)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
n(num_e)=f(u);
f(u)=num_e;
}

HZOJ Tree的更多相关文章

  1. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法

    二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...

  2. SAP CRM 树视图(TREE VIEW)

    树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...

  3. 无限分级和tree结构数据增删改【提供Demo下载】

    无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...

  4. 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  5. Leetcode 笔记 110 - Balanced Binary Tree

    题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...

  6. Leetcode 笔记 100 - Same Tree

    题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...

  7. Leetcode 笔记 99 - Recover Binary Search Tree

    题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...

  8. Leetcode 笔记 98 - Validate Binary Search Tree

    题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...

  9. Leetcode 笔记 101 - Symmetric Tree

    题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...

随机推荐

  1. 记一次PHP 数组基本用法

    以前不知道PHP数组可以这样叠加. $b = array( '2' => 'zhang', ); $a = array( ' => 'li' ) + $b; print_r($a); $b ...

  2. 使用Jedis操作Redis-使用Java语言在客户端操作---对key的操作

    //添加String类型的模拟数据. jedis.set("mykey", "2"); jedis.set("mykey2", " ...

  3. mysql8.0 安装版没有my.ini

    这时候,打开 benchmark,看一下实际路径就好了

  4. oracle-约束-序列

    概要图 一 约束 --问题:往表中插入数据的时候,可能出现一些问题,比如:重复插入数据,内容不对(性别) --如何保证数据库表中数据的完整性和一致性呢? 约束是强加在表上的规则或条件,确保数据库满足业 ...

  5. bzoj4974: [Lydsy八月月赛]字符串大师

    传送门 题目可转换为已知一个串kmp之后的nxt数组,求字典序最小的原串. 已知第i位结尾的串循环节长度位x,那么nxt[i]=i-x; 当nxt不为0时,s[i]=s[nxt[i]]; nxt为0时 ...

  6. web App libraries跟referenced libraries的一些问题

    该博文内容经参看网上其他资料归纳所成,并注明出处: 问题一:myeclipse中Web App Libraries无法自动识别lib下的jar包(http://blog.csdn.net/tianca ...

  7. WPF e.Systemkey的一个坑

    当用代码去控制按键盘F10按钮的时候,切换TabControl的标签页,然后再按其余的键盘键,无法响应 原因就是这个systemkey,是因为F10为系统的按键,用e.key==key.f10是无效的 ...

  8. vue中router以及route的使用

    路由基本概念 route,它是一条路由. { path: '/home', component: Home } routes,是一组路由. const routes = [ { path: '/hom ...

  9. 移动端fixed定位在底部,出现键盘后消失

    jq var h=$(window).height(); $(window).resize(function() { if($(window).height()<h){ $('.nav').hi ...

  10. 微服务开源生态报告 No.6

    「微服务开源生态报告」,汇集各个开源项目近期的社区动态,帮助开发者们更高效的了解到各开源项目的最新进展. 社区动态包括,但不限于:版本发布.人员动态.项目动态和规划.培训和活动. 非常欢迎国内其他微服 ...