传送门

解题思路

  前两个操作都比较基础。对于第三个操作分类讨论一下,首先如果当前根不是要操作点的子树,那么就无影响,直接查询操作点的子树即可。第二种是当前根是操作点的子树,那就找到当前根到操作点这条链的顶端(也就是操作点的儿子,这个儿子为当前根的祖先),然后将这块连续的\(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. bypass_safedog

    1.SQL注入 手工bypass要点 先通过破坏关键字测试出拦截规则 之后进行针对性绕过 1.Mysql 1.1.联合注入 0x01 and绕过 直接 and 1=1 直接就会被拦截 在数值的前面加特 ...

  2. 发光LED压降与工作电流总结

    一.常用的普通贴片0603LED 红色的压降为1.82-1.88V,电流5-8mA 绿色的压降为1.75-1.82V,电流3-5mA 橙色的压降为1.7-1.8V,电流3-5mA 兰色的压降为3.1- ...

  3. (转)Linux查看程序端口占用情况

    转:http://www.cnblogs.com/benio/archive/2010/09/15/1826728.html 今天发现服务器上Tomcat 8080端口起不来,老提示端口已经被占用. ...

  4. SpringBoot就这一篇全搞定

    Spring Boot从初识到实战 文章收集在 GitHub JavaEgg 中,欢迎star+指导 JavaEgg--<"Java技术员"成长手册>,包含Java基础 ...

  5. HTTPS 加密机制

    目录 1. HTTPS 概述 2. 对称加密 3. 非对称加密 4. 非对称加密改良方案 5. 非对称加密 + 对称加密 6. 中间人攻击 7. 数字证书 8. 数字签名 9. HTTPS 工作原理 ...

  6. Mysql 导入日文数据乱码问题

    做数据迁移后,通过ui发现有日文数据是乱码,通过ui直接修改日文则显示正常. 查了下资料,mysql字符集的作用如下: MySQL字符集设置 • 系统变量:– character_set_server ...

  7. git: 使用submodule进行托管

    问题描述: 当一个prj.git项目里引用了另外一个moduleA.git项目作为其一个子模块,由于该模块未完善后续可能将继续升级,也就是需要两套git分别管理prj.git与moduleA.git, ...

  8. 2019牛客多校第三场F-Planting Trees(单调队列)

    Planting Trees 题目传送门 解题思路 枚举每一个下边界,再枚举其对应的所有上边界,求出其对应区间内的最大最小值,当下边界一样的时候,其最大最小值可以随着上边界减小逐步更新.然后将这些最大 ...

  9. 2017 ICPC Asia Urumqi A.coins (概率DP + 期望)

    题目链接:Coins Description Alice and Bob are playing a simple game. They line up a row of nn identical c ...

  10. upc组队赛2 Master of GCD 【线段树区间更新 || 差分】

    Master of GCD 题目描述 Hakase has n numbers in a line. At fi rst, they are all equal to 1. Besides, Haka ...