以1号节点为根,弄出DFS序,我们发现,对于一个询问:(rt,u),以rt为根,u节点的子树中的最小点权,我们可以根据rt,u,1这三个节点在同一条路径上的相对关系来把它转化为以1为根的在DFS序上的区间询问(中间有一种情况要在树上倍增,理解了LCA的话应该很容易写出来)。

收获:

对于只有换根这种改变树的形态的操作,又只询问和子树相关的问题,可以不用动态树。

 /**************************************************************
Problem: 3306
User: idy002
Language: C++
Result: Accepted
Time:2264 ms
Memory:19948 kb
****************************************************************/ #include <cstdio>
#include <iostream>
#define oo 0x3f3f3f3f
#define N 100010
#define P 16
using namespace std; struct Node {
int v;
Node *ls, *rs;
}pool[N*], *tail=pool, *root; int n, m;
int head[N], wght[N], dest[N+N], next[N+N], etot;
int anc[N][P+], dep[N], in[N], out[N], vdf[N], idc; void update( Node *nd ) {
nd->v = min( nd->ls->v, nd->rs->v );
}
Node *build( int lf, int rg ) {
Node *nd = ++tail;
if( lf==rg ) {
nd->v = wght[vdf[lf]];
return nd;
}
int mid=(lf+rg)>>;
nd->ls = build( lf, mid );
nd->rs = build( mid+, rg );
update( nd );
return nd;
}
void modify( Node *nd, int lf, int rg, int pos, int val ) {
if( lf==rg ) {
nd->v = val;
return;
}
int mid=(lf+rg)>>;
if( pos<=mid ) modify( nd->ls, lf, mid, pos, val );
else modify( nd->rs, mid+, rg, pos, val );
update(nd);
}
int query( Node *nd, int lf, int rg, int L, int R ) {
if( L<=lf && rg<=R )
return nd->v;
int mid=(lf+rg)>>;
int rt = oo;
if( L<=mid ) rt = query( nd->ls, lf, mid, L, R );
if( R>mid ) rt = min( rt, query( nd->rs, mid+, rg, L, R ) );
return rt;
}
void adde( int u, int v ) {
etot++;
next[etot] = head[u];
dest[etot] = v;
head[u] = etot;
}
void dfs( int u ) {
++idc;
in[u] = idc;
vdf[idc] = u;
for( int p=; p<=P; p++ )
anc[u][p] = anc[anc[u][p-]][p-];
for( int t=head[u]; t; t=next[t] ) {
int v=dest[t];
anc[v][] = u;
dep[v] = dep[u]+;
dfs(v);
}
out[u] = idc;
}
int climb( int u, int t ) {
for( int p=; t; t>>=,p++ )
if( t& ) u=anc[u][p];
return u;
}
int lca( int u, int v ) {
if( dep[u]<dep[v] ) swap(u,v);
int t=dep[u]-dep[v];
u = climb( u, t );
if( u==v ) return u;
for( int p=P; p>=&&anc[u][]!=anc[v][]; p-- )
if( anc[u][p]!=anc[v][p] ) u=anc[u][p],v=anc[v][p];
return anc[u][];
}
int query( int rt, int u ) {
int ca=lca(rt,u);
if( rt==u ) {
return query( root, , idc, , idc );
} else if( ca==u ) {
int ans1=oo, ans2=oo;
u = climb( rt, dep[rt]-dep[u]- );
if( in[u]>= ) ans1 = query( root, , idc, , in[u]- );
if( out[u]<=n- ) ans2 = query( root, , idc, out[u]+, idc );
return min( ans1, ans2 );
} else {
return query( root, , idc, in[u], out[u] );
}
}
int main() {
scanf( "%d%d", &n, &m );
for( int i=,f,w; i<=n; i++ ) {
scanf( "%d%d", &f, &w );
wght[i] = w;
if( f ) adde(f,i);
}
anc[][] = ;
dep[] = ;
dfs();
root = build( , idc ); int crt=;
for( int t=,x,y; t<=m; t++ ) {
char ch[];
scanf( "%s", ch ); if( ch[]=='V' ) {
scanf( "%d%d", &x, &y );
modify( root, , idc, in[x], y );
} else if( ch[]=='E' ) {
scanf( "%d", &crt );
} else {
scanf( "%d", &x );
printf( "%d\n", query(crt,x) );
}
}
}

bzoj 3306的更多相关文章

  1. BZOJ 3306: 树 LCT + set 维护子树信息

    可以作为 LCT 维护子树信息的模板,写的还是比较优美的. 本地可过,bzoj 时限太紧,一直 TLE #include<bits/stdc++.h> #define setIO(s) f ...

  2. BZOJ 3306 树

    dfs序建线段树+分类讨论+写的有点长. #include<iostream> #include<cstdio> #include<cstring> #includ ...

  3. 【bzoj 3306】树

    Description 给定一棵大小为 n 的有根点权树,支持以下操作:  • 换根  • 修改点权      • 查询子树最小值 Input 第一行两个整数 n, Q ,分别表示树的大小和操作数.  ...

  4. BZOJ 2127: happiness [最小割]

    2127: happiness Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 1815  Solved: 878[Submit][Status][Di ...

  5. BZOJ 3275: Number

    3275: Number Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 874  Solved: 371[Submit][Status][Discus ...

  6. BZOJ 2879: [Noi2012]美食节

    2879: [Noi2012]美食节 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1834  Solved: 969[Submit][Status] ...

  7. bzoj 4610 Ceiling Functi

    bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...

  8. centos7 打开mysql 3306端口并 设置外部访问

    mysql安装后默认是localhost访问,如果需要外部访问可以设置一个新的账号把host改为%,意味着所有ip均可以访问 grant all privileges on *.* to 'outUs ...

  9. BZOJ 题目整理

    bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...

随机推荐

  1. JavaScript进阶--慕课网学习笔记

                         JAVASCRIPT—进阶篇 给变量取个名字(变量命名) 变量名字可以任意取,只不过取名字要遵循一些规则: 1.必须以字母.下划线或美元符号开头,后面可以跟字 ...

  2. 解决java计算中double类型结果不一致问题,使用BigDecimal解决

    一.需求:从数据表中读出一个double的数据,比如是3.5,没问题,但是如果再用3.5进行计算,比如乘以100,结果就是350了,而是35000000004 因为是浮点运算,所有语言中的浮点数都会有 ...

  3. 【算法】Base64编码

    1.说明 Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法. 2.编码 ASCII码 -> 十六进制码 -> ...

  4. JQuery怎么实现页面左侧菜单刷新后保留鼠标点击addclass的样式?

    $('ul.main-menu li a').each(function(){ if($($(this))[0].href==String(window.location)) $(this).pare ...

  5. js函数前加分号和感叹号是什么意思?有什么用?

    一般看JQuery插件里的写法是这样的 (function($) { //... })(jQuery); 今天看到bootstrap的javascript组件是这样写的 !function( $ ){ ...

  6. python_selenium自动化测试框架

    设计思路 本文整理归纳以往的工作中用到的东西,现汇总成基础测试框架提供分享. 框架采用python3 + selenium3 + PO + yaml + ddt + unittest等技术编写成基础测 ...

  7. django(2)基本指令

    打开 Linux 或 MacOS 的 Terminal (终端)直接在 终端中输入这些命令(不是 python 的 shell中) 如果是 windows 用 cmd(开始 搜索 cmd 或者 快捷键 ...

  8. Java多线程-Java多线程概述

    第一章 Java多线程概述 线程的启动 线程的暂停 线程的优先级 线程安全相关问题 1.1 进程与线程 进程:可以将运行在内存中的程序(如exe文件)理解为进程,进程是受操作系统管理的基本的运行单元. ...

  9. SQL中的left outer join,inner join,right outer join用法详解

    这两天,在研究SQL语法中的inner join多表查询语法的用法,通过学习,发现一个SQL命令,竟然涉及到很多线性代数方面的知识,现将这些知识系统地记录如下: 使用关系代数合并数据1 关系代数合并数 ...

  10. GreenPlum学习笔记:create table创建表

    二维表同样是GP中重要的存储数据对象,为了更好的支持数据仓库海量数据的访问,GP的表可以分成: 面向行存储的普通堆积表 面向列存储的AOT表(append only table) 当然AOT表也可以是 ...