传送门

解题思路

  前两个操作都比较基础。对于第三个操作分类讨论一下,首先如果当前根不是要操作点的子树,那么就无影响,直接查询操作点的子树即可。第二种是当前根是操作点的子树,那就找到当前根到操作点这条链的顶端(也就是操作点的儿子,这个儿子为当前根的祖先),然后将这块连续的\(dfs\)序挖掉,查询两边就行了。找这个点的时候用倍增即可。(暴力往上跳也能过)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib> using namespace std;
const int MAXN = 100005; inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) {f=ch=='-'?0:1;ch=getchar();}
while(isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?x:-x;
} int n,m,head[MAXN],cnt,to[MAXN<<1],nxt[MAXN<<1],w[MAXN],wt[MAXN],rt,num,g[MAXN][20];
int siz[MAXN],fa[MAXN],son[MAXN],id[MAXN],Min[MAXN<<2],tag[MAXN<<2],top[MAXN],dep[MAXN]; inline int min(int x,int y){
return x<y?x:y;
} inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
} void dfs1(int x,int f,int d){
dep[x]=d;fa[x]=f;siz[x]=1;g[x][0]=f;
for(int i=1;i<=18;i++) g[x][i]=g[g[x][i-1]][i-1];
int maxson=-1,u;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==f) continue;
dfs1(u,x,d+1);siz[x]+=siz[u];
if(siz[u]>maxson) {maxson=siz[u];son[x]=u;}
}
} void dfs2(int x,int topf){
id[x]=++num;wt[num]=w[x];
top[x]=topf;if(!son[x]) return;
dfs2(son[x],topf);int u;
for(int i=head[x];i;i=nxt[i]){
u=to[i];if(u==fa[x] || u==son[x]) continue;
dfs2(u,u);
}
} void build(int x,int l,int r){
if(l==r) {Min[x]=wt[l];return;}
int mid=(l+r)>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
Min[x]=min(Min[x<<1],Min[x<<1|1]);
} inline void pushdown(int x){
Min[x<<1]=tag[x];Min[x<<1|1]=tag[x];
tag[x<<1]=tag[x];tag[x<<1|1]=tag[x];
tag[x]=0;
} void update(int x,int l,int r,int L,int R,int k){
if(L<=l && r<=R) {Min[x]=k;tag[x]=k;return;}
int mid=(l+r)>>1;if(tag[x]) pushdown(x);
if(L<=mid) update(x<<1,l,mid,L,R,k);
if(mid<R) update(x<<1|1,mid+1,r,L,R,k);
Min[x]=min(Min[x<<1],Min[x<<1|1]);
} int query(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return Min[x];
int mid=(l+r)>>1,ret=0x7fffffff;if(tag[x]) pushdown(x);
if(L<=mid) ret=min(ret,query(x<<1,l,mid,L,R));
if(mid<R) ret=min(ret,query(x<<1|1,mid+1,r,L,R));
return ret;
} inline void updRange(int x,int y,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
update(1,1,n,id[top[x]],id[x],k);x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);update(1,1,n,id[x],id[y],k);
} inline int qRange(int x,int y){
if(fa[x]==y) return x;
for(int i=18;i>=0;i--){
if(fa[g[x][i]]==y) return g[x][i];
if(dep[fa[g[x][i]]]>dep[y]) x=g[x][i];
}
return x;
} inline int qSon(int x){
if(x==rt) return query(1,1,n,1,n);
if(id[rt]>id[x]+siz[x]-1 || id[rt]<id[x]) return query(1,1,n,id[x],id[x]+siz[x]-1);
int point=qRange(rt,x),ret=0x7fffffff;
if(id[point]+siz[point]<=n) ret=min(ret,query(1,1,n,id[point]+siz[point],n));
if(id[point]-1>=1) ret=min(ret,query(1,1,n,1,id[point]-1));return ret;
} int main(){
n=rd(),m=rd();int x,y,op,z;
for(int i=1;i<n;i++){
x=rd(),y=rd();
add(x,y),add(y,x);
}
for(int i=1;i<=n;i++) w[i]=rd();rt=rd();
dfs1(rt,0,1);dfs2(rt,rt);build(1,1,n);
while(m--){
op=rd();
if(op==1) x=rd(),rt=x;
if(op==2){
x=rd(),y=rd(),z=rd();
updRange(x,y,z);
}
if(op==3) {x=rd();printf("%d\n",qSon(x));}
}
return 0;
}

BZOJ 3083: 遥远的国度 (树剖+线段树)的更多相关文章

  1. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  2. BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树

    BZOJ_4551_[Tjoi2016&Heoi2016]树_树剖+线段树 Description 在2016年,佳媛姐姐刚刚学习了树,非常开心.现在他想解决这样一个问题:给定一颗有根树(根为 ...

  3. BZOJ_2157_旅游_树剖+线段树

    BZOJ_2157_旅游_树剖+线段树 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接.为了方便游客到达每个景点但 ...

  4. 【BZOJ5210】最大连通子块和 树剖线段树+动态DP

    [BZOJ5210]最大连通子块和 Description 给出一棵n个点.以1为根的有根树,点有点权.要求支持如下两种操作: M x y:将点x的点权改为y: Q x:求以x为根的子树的最大连通子块 ...

  5. [LNOI2014]LCA(树剖+线段树)

    \(\%\%\% Fading\) 此题是他第一道黑题(我的第一道黑题是蒲公英) 一直不敢开,后来发现是差分一下,将询问离线,树剖+线段树维护即可 \(Code\ Below:\) #include ...

  6. [CF1007D]Ants[2-SAT+树剖+线段树优化建图]

    题意 我们用路径 \((u, v)\) 表示一棵树上从结点 \(u\) 到结点 \(v\) 的最短路径. 给定一棵由 \(n\) 个结点构成的树.你需要用 \(m\) 种不同的颜色为这棵树的树边染色, ...

  7. LOJ#3088. 「GXOI / GZOI2019」旧词(树剖+线段树)

    题面 传送门 题解 先考虑\(k=1\)的情况,我们可以离线处理,从小到大对于每一个\(i\),令\(1\)到\(i\)的路径上每个节点权值增加\(1\),然后对于所有\(x=i\)的询问查一下\(y ...

  8. BZOJ3531-[Sdoi2014]旅行(树剖+线段树动态开点)

    传送门 完了今天才知道原来线段树的动态开点和主席树是不一样的啊 我们先考虑没有宗教信仰的限制,那么就是一个很明显的树剖+线段树,路径查询最大值以及路径和 然后有了宗教信仰的限制该怎么做呢? 先考虑暴力 ...

  9. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

  10. 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 ...

随机推荐

  1. 问题 |无法找到Python路径,需手动配置环境变量

    问题: 在命令行cmd输入Python,如果出现以下无法识别命令行的报错,说明在系统环境变量中无法找到对应之前安装的Python的路径,则需手动配置一下 怎么配置? 1.打开我的电脑——右键——属性— ...

  2. Windows API 查看器

    { http://www.dependencywalker.com/ } { Download the latest version here:  Download Version 2.2.6000 ...

  3. git——commit成功后,GitHub方格不变绿

    一通百度该设置的都设置了,还是不好使 发现有提示一栏 pull request的东西  在网上查貌似是因为两个分支内容不同 提示是否合并,还查到了不变绿可能的原因. Contributions未被Gi ...

  4. sql 性能优化 索引碎片

    1.索引 简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率.(1). 优点大大加快了数据库检索的速度,包 ...

  5. C++11下的关键字

    STL类:stack,queue,deque,priority_queue,map,set,multiset,bitset,vector 函数类:min,max,swap,sqrt,log,rever ...

  6. J2EE学习篇之--JQuery技术详解

    前面我们讲解了的J2EE的技术都是服务端的技术,下面我们来看一下前端的一些开发技术,这一篇我们来看一下jQuery技术 简介: jQuery由美国人John Resig创建,至今已吸引了来自世界各地的 ...

  7. P1493 分梨子

    P1493 分梨子 题目描述 Finley家的院子里有棵梨树,最近收获了许多梨子.于是,Finley决定挑出一些梨子,分给幼稚园的宝宝们.可是梨子大小味道都不太一样,一定要尽量挑选那些差不多的梨子分给 ...

  8. mac下nginx

    配置文件位置 /usr/local/etc/nginx/nginx.conf 简单命令 nginx -s quit 退出 nginx -s reload 重新加载 nginx -t 测试nginx.c ...

  9. 批处理禁止指定的IE的加载项

    步骤: 1.查找插件对应的 CLSID 获取 HKCU\Software\Microsoft\Windows\CurrentVersion\Ext\Stats 下的 CLSID, 然后在 HKCR\C ...

  10. pycharm中evaluate expression的用法

    pycharm中evaluate expression的用法 首先要用debug调试模式运行程序,在代码编辑处右键debug,或着选择右上角的小虫子图标点击. 然后保证整个程序运行的时候可以中断,然后 ...