题解:

写起来还稍微有点麻烦。
dfs序+线段树可以维护子树的整体修改和查询。 因此,这道题我们要往子树上靠。
我们首先从1号点进行dfs遍历,顺便求出点的dfs序和深度,然后我们采用倍增的思想,可以预处理出每个点的祖先是谁。然后可以在O(log(n))O(log(n))O(log(n))的时间复杂度内求出任意两点的lca(u,v)lca(u,v)lca(u,v)。
而现在整个树的根是可以改变的,因此,我们需要一个结论,也就是说当树的根节点被改变为root时候,u和v的新的lca,也就是newlca(u,v)=lca(u,v)xorlca(u,root)xorlca(v,root)newlca(u,v)=lca(u,v)xorlca(u,root)xorlca(v,root)newlca(u,v) = lca(u,v) xor lca(u,root) xor lca(v,root) (这个可以自己画画图看一下)。
找到newlca以后还不行,根据newlca与root的关系不一样,还需要进一步讨论。
1. 当newlca=rootnewlca=rootnewlca = root的时候,要操作的子树就是整颗树。
2. 当lca(newlca,root)!=newlcalca(newlca,root)!=newlcalca(newlca,root) != newlca 那么要操作的子树就是以1为根节点时候的newlca的子树。
3. 当lca(newlca,root)==newlcalca(newlca,root)==newlcalca(newlca,root) == newlca的时候,那么要操作的就是整颗树减去以(root到newlca链上深度为dep[newlca]-1的)点的子树。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define int long long
#define pr(x) cout<<#x<<":"<<x<<endl
const int maxn = 1e5+7;
int n,q;
struct edge{int u,v,nxt;
}es[maxn<<1];
int head[maxn];
int tot = 0;
void addedge(int u,int v){es[tot].u = u,es[tot].v = v,es[tot].nxt = head[u];head[u] = tot++;
}
int fa[maxn][22],dep[maxn];
int idx = 0,IN[maxn],OUT[maxn];
int segtree[maxn<<3],addmark[maxn<<3];
void init(){memset(fa,0,sizeof(fa));memset(head,-1,sizeof(head));memset(IN,0,sizeof(IN));memset(OUT,0,sizeof(OUT));memset(dep,0,sizeof(dep));tot = idx = 0;
}
void dfs(int u,int myfa,int dp){dep[u] = dp;IN[u] = ++idx;for(int e = head[u];e != -1;e = es[e].nxt){int v = es[e].v;if(v == myfa) continue;fa[v][0] = u;dfs(v,u,dp+1);}OUT[u] = ++idx;
}
void pushdown(int rt,int lft,int rgt){if(addmark[rt]){int mid = (lft + rgt)/2;addmark[2*rt] += addmark[rt];addmark[2*rt+1] += addmark[rt];segtree[2*rt] += addmark[rt]*(mid-lft+1);segtree[2*rt+1] += addmark[rt]*(rgt-mid);addmark[rt] = 0;}
}
void pushup(int rt){segtree[rt] = segtree[rt*2] + segtree[rt*2+1];
}
int val[maxn];
/*
void build(int rt,int L,int R){if(R == L) {segtree[rt] = val[L];}else{build(L,mid);build(mid+1,R);}
}*/
void ins(int rt,int lft,int rgt,int L,int R,int adv){if(rgt < L || lft > R) return ;if(L <= lft && R >= rgt) {segtree[rt] += (rgt-lft+1)*adv;addmark[rt] += adv;return ;}int mid = (lft + rgt) / 2;pushdown(rt,lft,rgt);ins(rt*2,lft,mid,L,R,adv);ins(rt*2+1,mid+1,rgt,L,R,adv);pushup(rt);
}
int ask(int rt,int lft,int rgt,int L,int R){if(rgt < L || lft > R) return 0;if(L <= lft && R >= rgt) return segtree[rt];pushdown(rt,lft,rgt);int mid = (lft + rgt)/2;return ask(rt*2,lft,mid,L,R) + ask(rt*2+1,mid+1,rgt,L,R);
}
void makelca(){for(int i = 1;i < 20;++i){for(int u = 1;u <= n;++u){fa[u][i] = fa[fa[u][i-1]][i-1];}}
}
int lca(int u,int v){if(dep[u] < dep[v]) swap(u,v);int dpc = dep[u] - dep[v];if(dpc){int t = 0;while(dpc){if(dpc & 1)u = fa[u][t];t++;dpc >>= 1;}}if(u == v) return u;for(int i = 19;u != v && i >= 0;--i ){if(fa[u][i] != fa[v][i]) {u = fa[u][i];v = fa[v][i];}}return fa[u][0];
}int root = 1;
main(){init();scanf("%lld%lld",&n,&q);for(int i = 1;i <= n;++i){scanf("%lld",&val[i]);}for(int i = 0;i < n-1;++i){int u,v;scanf("%lld%lld",&u,&v);addedge(u,v);addedge(v,u);}dfs(1,-1,0);makelca();for(int i = 1;i <= n;++i){ins(1,1,2*n,IN[i],IN[i],val[i]);ins(1,1,2*n,OUT[i],OUT[i],val[i]);}//计算lcafor(int i = 0;i < q;++i){int op ;scanf("%lld",&op);if(op == 1){scanf("%lld",&root);}else if(op == 2){int u,v,x;scanf("%lld%lld%lld",&u,&v,&x);int rt = lca(u,v)^lca(u,root)^lca(root,v);if(rt == root) ins(1,1,2*n,1,2*n,x);else if(lca(rt,root) != rt) ins(1,1,2*n,IN[rt],OUT[rt],x);else{int dpc = dep[root]-dep[rt]-1;int t = 0;int tmp = root;while(dpc){if(dpc&1)tmp = fa[tmp][t];t++;dpc >>= 1;}//cout<<tmp<<' '<<IN[tmp]<<' '<<OUT[tmp]<<endl;ins(1,1,2*n,1,2*n,x);ins(1,1,2*n,IN[tmp],OUT[tmp],-x);}}else if(op == 3){int v;scanf("%lld",&v);if(v == root){printf("%lld\n",ask(1,1,2*n,1,2*n)/2);}else if(lca(v,root) != v){printf("%lld\n",ask(1,1,2*n,IN[v],OUT[v])/2);}else{int tmp = root;int dpc = dep[root]-1-dep[v];int t = 0;while(dpc){if(dpc&1)tmp = fa[tmp][t];++t;dpc >>= 1;}int ans = (ask(1,1,2*n,1,2*n)-ask(1,1,2*n,IN[tmp],OUT[tmp]))/2;printf("%lld\n",ans);}}}//return 0;
}

codeforces E. Jamie and Tree LCA+dfs序+线段树相关推荐

  1. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  2. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  3. POJ - 2763 Housewife Wind LCA+dfs序+线段树

    q次询问求两个点之间的距离,并且可以随时修改某条边的长度,最短距离可以用lca来求,但是树上维护每一个点到root的距离必须要用dfs序来记录时间戳,在dfs的时候顺便记录每一条边(u,v)对应的v节 ...

  4. HDU - 6203 ping ping ping(LCA+dfs序+线段树)

    题目链接:点击查看 题目大意:给出一棵由n+1个节点组成的数,节点编号为0~n(这个无关紧要,预处理时所有节点以及n都自增1即可转换为正常的模型了),现在给出m组节点u和v,问若想让m组u和v都断开连 ...

  5. 【POJ - 3321】 Apple Tree(dfs序 + 线段树维护 或 dfs序 + 树状数组维护)

    题干: There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow in the t ...

  6. 求和(dfs序+线段树)

    题意: 已知有n个节点,有n−1条边,形成一个树的结构. 给定一个根节点k,每个节点都有一个权值,节点i的权值为vi​. 给m个操作,操作有两种类型: 1 a x :表示将节点a的权值加上x 2 a ...

  7. [CodeForces877 E. Danil and a Part-time Job]dfs序+线段树

    [CodeForces877 E.Danil and a Part-time Job]dfs序+线段树 分类:Data Structure SegMent Tree dfn 1. 题目链接 [Code ...

  8. bzoj3252攻略 贪心+dfs序+线段树

    题目链接:戳这里 3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 605  Solved: 255 [Submit][Status] ...

  9. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 339  Solved: 130 [Submit][Status][Discuss] ...

最新文章

  1. 智能电视验收测试软件,验收测试
  2. linux中probe函数中传递的参数来源(上)
  3. pthread_create函数编译时报错:undefined reference to 'pthread_create'
  4. 哈士奇与阿拉斯加的区别!
  5. BugkuCTF-reverse:入门逆向
  6. CSS3的transform:将元素旋转,缩放,移动,倾斜
  7. postgresql 修改字段名称
  8. bios升级工具_雨林木风U盘启动盘装系统制作工具再次升级。。。
  9. 深入理解java虚拟机JVM(上)
  10. Apache Commons Codec 1.7 发布
  11. usb接口供电不足_USB不被电脑识别,按F8有用吗?这篇文章告诉你
  12. 我用Python把抖音上的美女图片转字符画,期望的AI目标更进一步【机器学习算法实战小项目,k聚类算法图片转化字符画】
  13. 订单生产计划表范本_生产计划表(生产计划表格模板)
  14. 【论文精读】TransE 及其实现
  15. Anaconda下载及安装详细教程(图文)
  16. Xshell 5使用教程
  17. 软硬件交互 - 扫码枪
  18. C语言实现客房管理系统
  19. KeyError: 'labels [189] not contained in axis' Python DataFrame 合并后使用loc进行索引的时候出错问题分析以及解决方案
  20. Frodo and pillows

热门文章

  1. excel表格中添加combobox_Excel中两个表格对比,找出不同数据
  2. android loading封装_我们经常用的Loading动画居然还有这种姿势
  3. 二叉树序列化与反序列化相关题目(Leetcode题解-Python语言)
  4. mysql改表字段类型导致数据丢失_故障分析 | 记一次 MySQL 主从双写导致的数据丢失问题【转】...
  5. [蓝桥杯][算法提高VIP]断案-枚举
  6. KMP模式串匹配+Compress Words CodeForces - 1200E
  7. jsbridge实现及原理_JSBridge 实现原理解析
  8. word List 11
  9. 对全局变量,static静态变量的理解
  10. 【NOI2019】回家路线【无后效性dp状态设计】【斜率优化】