【Luogu】P3979遥远的国度(树链剖分)
不会换根从暑假开始就困扰我了……拖到现在……
会了还是很激动的。
换根操作事实上不需要(也不能)改树剖本来的dfs序……只是在query上动动手脚……
设全树的集合为G,以root为根,u在原根到新根的链上的子树集合为G',则有查询区间=G-G'……
然后查询的时候就查G-G'就行
- #include<cstdio>
- #include<cstdlib>
- #include<cctype>
- #include<algorithm>
- #include<cstring>
- #define left (rt<<1)
- #define right (rt<<1|1)
- #define mid ((l+r)>>1)
- #define lson l,mid,left
- #define rson mid+1,r,right
- #define maxn 100020
- using namespace std;
- inline long long read(){
- long long num=,f=;
- char ch=getchar();
- while(!isdigit(ch)){
- if(ch=='-') f=-;
- ch=getchar();
- }
- while(isdigit(ch)){
- num=num*+ch-'';
- ch=getchar();
- }
- return num*f;
- }
- struct Edge{
- int next,to;
- }edge[maxn*];
- int head[maxn],num;
- inline void add(int from,int to){
- edge[++num]=(Edge){head[from],to};
- head[from]=num;
- }
- int tree[maxn*];
- int tag[maxn*];
- int size[maxn];
- int deep[maxn];
- int son[maxn];
- int father[maxn];
- int top[maxn];
- int dfn[maxn];
- int back[maxn],ID;
- int q[maxn];
- int s[maxn][];
- int n,m;
- void find(int x,int fa){
- deep[x]=deep[fa]+; size[x]=;
- for(int i=head[x];i;i=edge[i].next){
- int to=edge[i].to;
- if(to==fa) continue;
- father[to]=x;
- s[to][]=x;
- find(to,x);
- size[x]+=size[to];
- if(son[x]==||size[son[x]]<size[to]) son[x]=to;
- }
- }
- void unionn(int x,int Top){
- dfn[x]=++ID; back[ID]=x;
- top[x]=Top;
- if(!son[x]) return;
- unionn(son[x],Top);
- for(int i=head[x];i;i=edge[i].next){
- int to=edge[i].to;
- if(to==father[x]||to==son[x]) continue;
- unionn(to,to);
- }
- }
- inline void pushup(int rt){
- tree[rt]=min(tree[left],tree[right]);
- }
- void pushdown(int rt){
- if(tag[rt]==-) return;
- tag[left]=tag[right]=tag[rt];
- tree[left]=tree[right]=tag[rt];
- tag[rt]=-;
- return;
- }
- void build(int l,int r,int rt){
- tag[rt]=-;
- if(l==r){
- tree[rt]=q[back[l]];
- return;
- }
- build(lson);
- build(rson);
- pushup(rt);
- }
- void memseg(int from,int to,int num,int l,int r,int rt){
- if(from<=l&&to>=r){
- tree[rt]=tag[rt]=num;
- //printf("%d %d l=%d r=%d %d\n",from,to,l,r,num);
- return;
- }
- pushdown(rt);
- if(from<=mid) memseg(from,to,num,lson);
- if(to>mid) memseg(from,to,num,rson);
- pushup(rt);
- return;
- }
- int query(int from,int to,int l,int r,int rt){
- if(from<=l&&to>=r) return tree[rt];
- pushdown(rt);
- int ans=0x7fffffff;
- if(from<=mid) ans=min(ans,query(from,to,lson));
- if(to>mid) ans=min(ans,query(from,to,rson));
- return ans;
- }
- int root;
- void update(int from,int to,int num){
- while(top[from]!=top[to]){
- if(deep[top[from]]<deep[top[to]]) swap(from,to);
- memseg(dfn[top[from]],dfn[from],num,,n,);
- from=father[top[from]];
- }
- if(deep[from]>deep[to]) swap(from,to);
- memseg(dfn[from],dfn[to],num,,n,);
- return;
- }
- int LCA(int from,int to){
- if(deep[from]<deep[to]) swap(from,to);
- int f=deep[from]-deep[to];
- for(int i=;(<<i)<=f;++i)
- if(f&(<<i)) from=s[from][i];
- if(from==to) return from;
- for(int i=;i>=;--i){
- if(s[from][i]==s[to][i]) continue;
- from=s[from][i];
- to=s[to][i];
- }
- return s[from][];
- }
- inline void prepare(){
- for(int j=;j<=;++j)
- for(int i=;i<=n;++i) s[i][j]=s[s[i][j-]][j-];
- }
- int ask(int o){
- if(root==) return query(dfn[o],dfn[o]+size[o]-,,n,);
- int lca=LCA(root,o);
- if(lca!=o) return query(dfn[o],dfn[o]+size[o]-,,n,);
- else{
- int now=root;
- for(int i=;i>=;--i)
- if(deep[s[now][i]]>deep[o]) now=s[now][i];
- int ans=0x7fffffff;
- if(dfn[now]>) ans=min(ans,query(,dfn[now]-,,n,));
- if(dfn[now]+size[now]<=n) ans=min(ans,query(dfn[now]+size[now],n,,n,));
- return ans;
- }
- }
- int main(){
- n=read(),m=read();
- for(int i=;i<n;++i){
- int from=read(),to=read();
- add(from,to);
- add(to,from);
- }
- for(int i=;i<=n;++i) q[i]=read();
- root=read();
- find(,);
- unionn(,);
- build(,n,);
- prepare();
- for(int i=;i<=m;++i){
- int opt=read();
- if(opt==) root=read();
- else if(opt==){
- int x=read(),y=read(),z=read();
- update(x,y,z);
- }
- else{
- int x=read();
- printf("%d\n",ask(x));
- }
- }
- return ;
- }
- /*
- 10 10
- 1 2
- 2 3
- 2 4
- 1 5
- 5 6
- 5 10
- 5 7
- 7 8
- 7 9
- 5 1 2 3 6 4 7 8 9 10
- 1
- */
话说写博客超简略的我简直是业界毒瘤啊……
【Luogu】P3979遥远的国度(树链剖分)的更多相关文章
- 洛谷P3979 遥远的国度 树链剖分+分类讨论
题意:给出一棵树,这棵树每个点有权值,然后有3种操作.操作一:修改树根为rt,操作二:修改u到v路径上点权值为w,操作三:询问以rt为根x子树的最小权值. 解法:如果没有修改树根操作那么这题就是树链剖 ...
- [luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点 ...
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- BZOJ 3083 遥远的国度(树链剖分+LCA)
Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...
- 【bzoj3083】遥远的国度 树链剖分+线段树
题目描述 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn ...
- BZOJ 3083: 遥远的国度(树链剖分+DFS序)
可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...
- BZOJ 3083 遥远的国度 树链剖分+线段树
有换根的树链剖分的裸题. 在换根的时候注意讨论. 注意数据范围要开unsigned int或longlong #include<iostream> #include<cstdio&g ...
- 【Luogu P3384】树链剖分模板
树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就 ...
- BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 1280 MBSubmit: 3127 Solved: 795[Submit][Status][Discu ...
- luoguP3979 遥远的国度 树链剖分
\(1, 2\)操作没什么好说的 对于\(3\)操作,分三种情况讨论下 \(id = rt\)的情况下,查整棵树的最小值即可 如果\(rt\)在\(1\)号点为根的情况下不在\(id\)的子树中,那么 ...
随机推荐
- MovieReview—Kingsman THE SECRET SERVICE(王牌特工之特工学院)
Brain Storming Mr. Valentine's Day see excess human beings as the Earth's virus and try to e ...
- ThinkPHP笔记——开启debug调试模式
debug+trace模式可以查看开发过程中TP的错误信息,可以更好地帮助开发者debug.但是debug模式的开启还不是简单的在配置文件中中设置就可以的,经过查资料摸索,找到一种有效的方法. 首先在 ...
- Spark源码分析之-Storage模块
原文链接:http://jerryshao.me/architecture/2013/10/08/spark-storage-module-analysis/ Background 前段时间琐事颇多, ...
- 【转】 iOS学习之NSBundle介绍和使用
bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle, cocoa提供了类NSBun ...
- solver
slover中有type,用于优化算法的选择,有6种: Stochastic Gradient Descent (type: “SGD”), AdaDelta (type: “AdaDelta”), ...
- BCB:Windows消息处理
Windows消息处理 BCB 本文研究了BCB中的消息处理机制,在此基础上提出了处理Windows消息和自定义消息响应的方法和建立动态和静态消息映射的技巧. C++ Builder作为一种RAD方式 ...
- helm install
reference 前提:已安装k8s:v1.10.4 helm install on master(无需下载官方tar包) 链接:https://pan.baidu.com/s/1Ji3Ru1pTQ ...
- springmvc的第一个程序
文中用的框架版本:spring 3,hibernate 3,没有的,自己上网下. web.xml配置: <?xml version="1.0" encoding=" ...
- 抓取oracle建表语句及获取建表ddl语句
抓取oracle建表语句及获取建表ddl语句 1.抓取代码如下: 1.1.产生表的语法资料 DECLARE-- v_notPartTable VARCHAR2(1000):= '&2'; -- ...
- Android读书笔记四
第四章 这是一次源代码之旅,学到了如何下载和编译Android源代码和Linux内核源代码.来详细阐述一下一些具体过程 一.Android源代码下载环境 1.安装下载Android源代码的环境配置 ( ...