看到换根果断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. git与github建立链接(将本次项目与网络GitHub同步)(二)

    第一步:我们需要先创建一个本地的版本库(其实也就是一个文件夹). 你可以直接右击新建文件夹,也可以右击打开Git bash命令行窗口通过命令来创建. 现在我通过命令行在桌面新建一个TEST文件夹(你也 ...

  2. python自动化--批量执行测试之生成报告

    一.生成报告 1.先执行一个用例,并生成该用例的报告 # -*- coding: utf-8 -*- from selenium import webdriver from selenium.webd ...

  3. hive如何配置支持事务及insert、update、delete

    Hive从0.14版本开始支持事务和行级更新,但缺省是不支持的,需要一些附加的配置.要想支持行级insert.update.delete,需要配置Hive支持事务. 一.Hive具有ACID语义事务的 ...

  4. windows 操作系统下git报filename too long 处理方法

    两种方法解决: 一是通过修改配置文件 [core] repositoryformatversion = filemode = false bare = false logallrefupdates = ...

  5. iview 中table列 一列显示多个数据(后台返回数组显示在列内)

    一.首先出现的是比较复杂的一种情况(多个key) 1.首先页面显示效果如下 2.后台返回数据格式如下: 3.在iview中table的columns中的render函数: 4.具体代码 render: ...

  6. itextsharp 1.0

    1 效果图 2.代码 引用组件: using iTextSharp.text;using iTextSharp.text.pdf;using System;using System.Data;usin ...

  7. Listview的条目item内的点击响应事件

    还是这张图 这里的历史列表就是一个ListView,抛开该界面中ScrollView或者RecycleView与该ListView会有冲突,所谓的冲突,说白了就是父控件与子控件两者间的关系冲突,该冲突 ...

  8. vue学习之组件(component)(一)

    组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能.在有些情况下, ...

  9. git 报错:没有权限 remote: error: unable to unlink old 'README.md' (Permission denied)

    解决:

  10. html5之本地数据库

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...