【树剖】CF916E Jamie and Tree
好吧这其实应该不是树剖...
因为只要求子树就够了,dfs就好了
大概就是记录一个全局根root
多画几幅图会发现修改时x,y以root为根时的lca为以1为根时的lca(x,y),lca(root,x),lca(root,y)中深度最大的一个
然后就可以做了
然后分类讨论当前更改操作节点x(更新即LCA(x,y),询问则就是x)和root的关系:
(接下来有关操作都以1为根)
1.x=root: 即询问/修改整颗树的权值和
2.root不在x的子树内:这样的话这里x的子树是没有被影响到的,直接修改就好了
3.root在x的子树内:画图发现(不会证明)从root到x的路径上的最后一个节点(不包括root和x)的子树是不要修改的,其他都要修改,这里用一下容斥就好了
维护区间和用线段树,lca用倍增(因为后面倍增还可以用来求路径,方便)
大概就好了
#include<bits/stdc++.h>
#define int long long
#define writeln(x) write(x),puts("")
using namespace std;
inline int read(){
int ans=,f=;char chr=getchar();
while(!isdigit(chr)){if(chr=='-') f=-;chr=getchar();}
while(isdigit(chr)){ans=(ans<<)+(ans<<)+chr-;chr=getchar();}
return ans*f;
}void write(int x){
if(x<) putchar('-'),x=-x;
if(x>) write(x/);
putchar(x%+'');
}const int M = 1e5+;
int head[M],ver[M<<],nxt[M<<],tot,n,m,dfn[M],b[M],a[M],fa[M][],sz[M],T,dep[M],s[M<<],lz[M<<],root,x,y,z,t,ans;
inline void add(int x,int y){ver[++tot]=y,nxt[tot]=head[x],head[x]=tot;}
void dfs(int x,int f){
dfn[x]=++T,fa[x][]=f,b[dfn[x]]=a[x],dep[x]=dep[f]+,sz[x]=;
for(int i=;(<<i)<=dep[x];i++)fa[x][i]=fa[fa[x][i-]][i-];
for(int i=head[x];i;i=nxt[i]){
if(ver[i]==f) continue;
dfs(ver[i],x);
sz[x]+=sz[ver[i]];
}
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=;i>=;i--)if(dep[x]-(<<i)>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=;i>=;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][];
}
#define ls (i<<1)
#define rs (i<<1|1)
#define mid (l+r>>1)
inline void Push_Up(int i){s[i]=s[ls]+s[rs];}
inline void Push_Down(int i,int l,int r){
if(!lz[i]) return;
s[ls]+=lz[i]*(mid-l+);
s[rs]+=lz[i]*(r-mid);
lz[ls]+=lz[i],lz[rs]+=lz[i];
lz[i]=;
}
void Build(int i,int l,int r){
if(l==r) return (void)(s[i]=b[l]);
Build(ls,l,mid),Build(rs,mid+,r);
Push_Up(i);
}
void Update(int i,int l,int r,int ql,int qr,int x){
if(ql<=l&&r<=qr)return (void)(s[i]+=(r-l+)*x,lz[i]+=x);
Push_Down(i,l,r);
if(ql<=mid) Update(ls,l,mid,ql,qr,x);
if(qr>mid) Update(rs,mid+,r,ql,qr,x);
Push_Up(i);
}
int Query(int i,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr) return s[i];
int ans=;Push_Down(i,l,r);
if(ql<=mid) ans+=Query(ls,l,mid,ql,qr);
if(qr>mid) ans+=Query(rs,mid+,r,ql,qr);
return ans;
}
inline int Get_Point(int x,int y){
int l1=LCA(x,y),l2=LCA(x,root),l3=LCA(y,root);
if(dep[l1]<dep[l2]) swap(l1,l2);
if(dep[l1]<dep[l3]) swap(l1,l3);
return l1;
}
inline Get(int x,int d){for(int i=;i>=;i--) if((<<i)&d) x=fa[x][i];return x;}
inline void Solve_1(){
x=read(),y=read(),z=read();
t=Get_Point(x,y);
if(t==root) return (void)(Update(,,n,,n,z));
if(dfn[t]>dfn[root]||dfn[t]+sz[t]-<dfn[root]) return (void)(Update(,,n,dfn[t],dfn[t]+sz[t]-,z));
int tmp=Get(root,dep[root]-dep[t]-);
Update(,,n,,n,z);Update(,,n,dfn[tmp],dfn[tmp]+sz[tmp]-,-z);
}
inline void Solve_2(){
x=read();
if(x==root) return (void)(writeln(Query(,,n,,n)));
if(dfn[x]>dfn[root]||dfn[x]+sz[x]-<dfn[root]) return (void)(writeln(Query(,,n,dfn[x],dfn[x]+sz[x]-)));
int tmp=Get(root,dep[root]-dep[x]-);
ans=Query(,,n,,n);ans-=Query(,,n,dfn[tmp],dfn[tmp]+sz[tmp]-);
writeln(ans);
}
signed main(){
n=read(),m=read();
for(int i=;i<=n;i++) a[i]=read();
for(int i=;i<n;i++)x=read(),y=read(),add(x,y),add(y,x);
dfs(,);Build(,,n);root=;
while(m--){
int opt=read();
if(opt==) root=read();
if(opt==) Solve_1();
if(opt==) Solve_2();
}
return ;
}
【树剖】CF916E Jamie and Tree的更多相关文章
- CF916E Jamie and Tree
CF916E Jamie and Tree 题意翻译 有一棵n个节点的有根树,标号为1-n,你需要维护以下三种操作 1.给定一个点v,将整颗树的根变为v 2.给定两个点u, v,将lca(u, v)所 ...
- CF916E Jamie and Tree 解题报告
CF916E Jamie and Tree 题意翻译 有一棵\(n\)个节点的有根树,标号为\(1-n\),你需要维护一下三种操作 1.给定一个点\(v\),将整颗树的根变为\(v\) 2.给定两个点 ...
- 题解 [CF916E] Jamie and Tree
题面 解析 这题考试时刚了四个小时. 结果还是爆零了 主要就是因为\(lca\)找伪了. 我们先考虑没有操作1,那就是裸的线段树. 在换了根以后,主要就是\(lca\)不好找(分类讨论伪了). 我们将 ...
- SPOJ Query on a tree III (树剖(dfs序)+主席树 || Splay等平衡树)(询问点)
You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose ...
- SPOJ375Query on a tree I(树剖+线段树)(询问边)
ιYou are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- POJ3237 Tree(树剖+线段树+lazy标记)
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbe ...
- codeforces 916E Jamie and Tree dfs序列化+线段树+LCA
E. Jamie and Tree time limit per test 2.5 seconds memory limit per test 256 megabytes input standard ...
- SP375 QTREE - Query on a tree (树剖)
题目 SP375 QTREE - Query on a tree 解析 也就是个蓝题,因为比较长 树剖裸题(基本上),单点修改,链上查询. 顺便来说一下链上操作时如何将边上的操作转化为点上的操作: 可 ...
- 2019.01.19 codeforces343D.Water Tree(树剖+ODT)
传送门 ODTODTODT板子题. 支持子树01覆盖,路径01覆盖,询问一个点的值. 思路:当然可以用树剖+线段树,不过树剖+ODTODTODT也可以很好的水过去. 注意修改路径时每次跳重链都要修改. ...
随机推荐
- Feign Request header is too large
Feign远程调用时数据量过大报错 看异常提示猜测Feign在请求其他服务时,将数据存在了header,导致数据量过大报错 MultiValueMap<String, String> pa ...
- 牛客D-Where are you /// kruskal+tarjan找无向图内的环
题目大意: https://ac.nowcoder.com/acm/contest/272/D 在一个无向图中,给定一个起点,从起点开始走遍图中所有点 每条边有边权wi,表示第一次经过该道路时的花费( ...
- POJ 4718 /// 树链剖分+线段树区间合并 求树上两点间的LCIS长度
题目大意: 给定n个点 每个点都有权值 接下来给定树的n条边 第 i 个数 a[i] 表示 i+1到a[i]之间 有一条边 给定q q个询问 每次询问给出 x y 求x到y的最长上升子序列的长度 题解 ...
- 【POJ】1502 MPI Maelstrom
题目链接:http://poj.org/problem?id=1502 题意:一个处理器给n-1个处理器发送广播,问最短时间.广播时并发,也就是各个路径就大的一方.输入如果是x的话说明两个处理器不能相 ...
- D3.js比例尺 定量比例尺 之 线性比例尺(v3版本)
定量比例尺 : 数学上有函数的概念,不是编程中所说的函数,如线性函数.指数函数.对数函数等,而指的是一个量随着另一个量的变化而变化.例如有一下线性函数 : y=2x+1该函数在二维坐标系中绘制出来的图 ...
- Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)
简单介绍一下,本框架的基本功能点: Spring:整个框架的主体部分,这个自不用说. SpringMVC:MVC部分我还是比较喜欢Spring的. MyBatis:选型的时候选择这个ORM主要也是考虑 ...
- java笔试之从单向链表中删除指定值的节点
输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针. 链表的值不能重复 构造过程,例如 1 -> 2 3 -> 2 5 -> 1 4 ...
- python日常使用
os.path.splitext('C:\py\wxPython.gif') 得到扩展名的函数 os.remove(删除文件) os.listdir(显示该目录下的文件) os.getcwd(获取当 ...
- CSS动画库——animate.css的使用
Animate.css是一款强大的CSS3动画库 官网地址:https://daneden.github.io/animate.css/ 使用方法如下所示: (1)下载animate.css 下载地址 ...
- fiddler突然间抓不到包了
1.一直使用fiddler抓包,但是近几天fiddler突然间抓不到过滤地址的包了. 2.重装fiddler,未能解决. 3.设置取消浏览器的代理,未能解决. 4.关闭杀毒软件,未能解决. 5.换了火 ...