可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y]-1  ed[y]+1 -- n 的最小值,其中y是root的祖先,x的儿子

PS:好久没做题,线段树都查了好久QAQ,还是没查出错来,最后只能cheat一个程序了QAQ

CODE:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define maxn 100010
#define maxm 200020
typedef long long ll ;
struct edges{
 int to,next;
}edge[maxm];
int next[maxn],l,n,m;
int addedge(int x,int y){
 edge[++l]=(edges){y,next[x]};next[x]=l;
 edge[++l]=(edges){x,next[y]};next[y]=l;
 return 0;
}
ll _min(ll x,ll y){
 if (x==0) return y;
 if (y==0) return x;
 return min(x,y);
}
int dep[maxn],fa[maxn],sum[maxn],ch[maxn],pre[maxn],pos[maxn],add[maxn],lef[maxn],righ[maxn];
int cl;
bool b[maxn];
int dfs(int u){
 dep[u]=dep[fa[u]]+1;
 sum[u]=1;b[u]=1;
 for (int i=next[u];i;i=edge[i].next)
  if (!b[edge[i].to]){
   fa[edge[i].to]=u;
   dfs(edge[i].to);
   sum[u]+=sum[edge[i].to];
   ch[u]=sum[edge[i].to]>sum[ch[u]]?edge[i].to:ch[u];
  }
 return 0;
}
int heavy(int u,bool bo){
 cl++;
 pos[add[cl]=u]=cl;
 b[u]=1;lef[u]=cl;
 if (bo) pre[u]=u;
 else pre[u]=pre[fa[u]];
 if (ch[u]) heavy(ch[u],0);
 for (int i=next[u];i;i=edge[i].next)
  if (!b[edge[i].to])
   heavy(edge[i].to,1);
 righ[u]=cl;
 return 0;
}
struct TREE{
 int l,r;ll x;bool lazy;
}t[maxn*8];
ll s[maxn];
int buildtree(int x,int l,int r){
 t[x].l=l;t[x].r=r;
 if (l==r) {t[x].x=s[add[l]];return 0;}
 buildtree(x<<1,l,(l+r)>>1);
 buildtree((x<<1)+1,((l+r)>>1)+1,r);
 t[x].x=_min(t[x<<1].x,t[(x<<1)+1].x);
 return 0;
}
int pushdown(int x){
 if (t[x].lazy) {
  t[x<<1].x=t[(x<<1)+1].x=t[x].x;
  t[x<<1].lazy=t[(x<<1)+1].lazy=1;
  t[x].lazy=0;
 }
 return 0;
}
ll cha(int x,int x1,int y1){
 int l=t[x].l,r=t[x].r;
 if (l>y1||r<x1) return 0;
 if (l==r) return (t[x].x);
 if (l>=x1&&r<=y1) return t[x].x;
 pushdown(x);
 return _min(cha(x<<1,x1,y1),cha((x<<1)+1,x1,y1));
}
int gai(int x,ll y,int x1,int y1){
 int l=t[x].l,r=t[x].r;
 if (l>y1||r<x1) return 0;
 if (l==r) {t[x].x=y;return 0;}
 if (l>=x1&&r<=y1) {t[x].lazy=1;t[x].x=y;return 0;}
 pushdown(x);
 gai(x<<1,y,x1,y1);gai((x<<1)+1,y,x1,y1);
 t[x].x=_min(t[x<<1].x,t[(x<<1)+1].x);
 return 0;
}
int change(int l,int r,ll x){
 for (;;){
  if (pre[l]==pre[r]) {
   if (dep[l]>dep[r]) swap(l,r);
   gai(1,x,pos[l],pos[r]);
   return 0;
  }else{
   if (dep[pre[l]]<dep[pre[r]]) swap(l,r);
   gai(1,x,pos[pre[l]],pos[l]);
   l=fa[pre[l]];
  }
 }
 return 0;
}
int root,tem;
bool check(int x){
 int y=root;
 while (fa[y]!=0){
  if (fa[y]==x) {tem=y;return 1;}
  if (dep[fa[y]]<dep[x]) return 0;
  if (pre[fa[y]]==pre[x]) {tem=ch[x];return 1;}
  y=pre[fa[y]];
 }
 return 0;
}
ll query(int x){
 if (!check(x))return (cha(1,lef[x],righ[x]));
 else return (_min(cha(1,1,lef[tem]-1),cha(1,righ[tem]+1,n)));
}
int main(){
 scanf("%d%d",&n,&m);
 for (int i=1;i<n;i++) {
  int x,y;
  scanf("%d%d",&x,&y);
  addedge(x,y);
 }
 for (int i=1;i<=n;i++) scanf("%lld",s+i);
 memset(b,0,sizeof(b));
 dfs(1);
 memset(b,0,sizeof(b));
 heavy(1,1);
 buildtree(1,1,n);
 scanf("%d",&root);
 while (m--){
  int opt,l,r;ll x;
  scanf("%d",&opt);
  if (opt==1) scanf("%d",&root);
  if (opt==2) {
   scanf("%d%d%lld",&l,&r,&x);
   change(l,r,x);
  }
  if (opt==3){
   scanf("%d",&l);
   printf("%lld\n",query(l));
  }
 }
 return  0;
}

转载于:https://www.cnblogs.com/New-Godess/p/4348954.html

BZOJ 3083: 遥远的国度(树链剖分+DFS序)相关推荐

  1. bzoj 3083 遥远的国度——树链剖分+线段树维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3083 int 的范围是 2^31 - 1 ,所以权值是不是爆 int 了-- O( nlog ...

  2. BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

    题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...

  3. bzoj3252攻略(线段树+dfs序)或者(树链剖分+dfs)

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

  4. BZOJ3083: 遥远的国度(树链剖分)

    题意 $n$个节点的树,每个点有权值,支持三种操作 1. 换根 2.把$x$到$y$路径上节点权值变为$z$ 3.询问路径最小值 Sol 啥?你说这是TopTree的裸题?那你写去啊 很显然,如果没有 ...

  5. 简单dfs序 + 树链剖分

    树链剖分 DFS序 先来讲一讲DFS序是什么东西,直接上图,方便理解. 估计巨巨们应该知道了DFS序的两个重要的东西,in,outin,outin,out数组. ininin数组就是这个点进入DFS的 ...

  6. 树链剖分 or 根号分治 + dfs序 + 树状数组 ---- CF1254 D. Tree Queries

    题目链接 题目大意: 问题转化: 很容易发现:假设修改的节点是vvv. 1.vvv的子树sonvson_vsonv​直接加上(n−size[sonv])n×d\frac{(n-size[son_v]) ...

  7. 蒟蒻浅谈树链剖分之一——两个dfs操作

    树链剖分,顾名思义就是将树形的结构剖分成链,我们以此便于在链上操作 首先我们需要明白在树链剖分中的一些概念 重儿子:某节点所有儿子中子树最多的儿子 重链:有重儿子构成的链 dfs序:按重儿子优先遍历时 ...

  8. BZOJ 3779 重组病毒 LCT,树链剖分,线段树

    题意: 给一棵树,每个点一开始颜色互不相同,支持三个操作                 1. 将一个点到根的路径染成一种新的颜色                 2. 将一个新的点设为根,并将原来的 ...

  9. BZOJ 2157 「国家集训队」旅游(树链剖分,线段树,边权转点权)【BZOJ计划】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 题目链接 https://hydro.ac/d/bzoj/p/2157 是 hydro 的 BZOJ ...

最新文章

  1. 腾讯推出高性能 RPC 开发框架
  2. 从数据集到2D和3D方法,一文概览目标检测领域进展
  3. 万亿新基建,AI“芯”机遇在哪?| CCF-GAIR 2020
  4. Android开发--详解SharedPreference/PreferenceActivity
  5. gradle mavenCentral()、jcenter()、google()仓库配置成阿里云
  6. python基础知识下载_Python基础知识(一)
  7. oracle 多个with as
  8. 基于JAVA+SpringMVC+Mybatis+MYSQL的仿百度网盘系统
  9. C++之临时对象、常引用和浅拷贝探究
  10. 动机的寓言:孩子为谁在玩
  11. Spring boot常见标签、注解解释
  12. 【Android】Scrollview返回顶部,快速返回顶部的功能实现,详解代码。
  13. 手摸手教你git配置ssh
  14. 【图像分割】基于matlab GUI图像提取【含Matlab源码 702期】
  15. 【2022最新版】微服务面试题总结(65道题含答案解析)
  16. 量子计算(三):有哪些机构或公司参与量子计算的研发
  17. 爬取搜狗微信文章笔记2
  18. Win300英雄服务器不显示,win10系统玩不了300英雄的还原步骤
  19. Quartus软件及器件库下载及安装
  20. 抽象类和接口的区别(精简)

热门文章

  1. 绩效考核中什么是KPI和KRA
  2. Close window without alert
  3. 开源目标检测算法用于交通标志检测全方位评估
  4. 初级java程序员怎样快速提升自己
  5. Python工具整合,为程序员和新手准备的 8 大 Python 工具
  6. Github1.3万星,迅猛发展的JAX对比TensorFlow、PyTorch
  7. TensorFlow全球下载量破1亿,Jeff Dean激动不已
  8. 深度隐式表达系列 (一)
  9. 对!这就是你要的pandas数据清洗练习题(❤️)
  10. 机器学习(十)Mean Shift 聚类算法