第一次写链剖,于是挑了个简单的裸题写。

以下几点要注意:

1.链剖中的height是从根到该店经过的轻边个数

2.分清num与sum。。。。。

#include<cstdio>
#include<algorithm>
using namespace std ; const int MAXN = * + ;
const int MAX_SIZE = * + ;
int N , Q ; int max_equal ( int & a , const int b ) { if ( a < b ) a = b ; return a ; } namespace Seg { int maxv [ MAX_SIZE * ] ;
int sumv [ MAX_SIZE * ] ;
int value [ MAXN ] ;
int l , r , v ; void maintain ( const int o ) {
const register int o1 = o << , o2 = o << | ;
maxv [ o ] = max ( maxv [ o1 ] , maxv [ o2 ] ) ;
sumv [ o ] = sumv [ o1 ] + sumv [ o2 ] ;
} void __build ( const int o , const int L , const int R ) {
if ( R - L == ) maxv [ o ] = sumv [ o ] = value [ L ] ;
else {
const int M = ( L + R ) / ;
__build ( o << , L , M ) ;
__build ( o << | , M , R ) ;
maintain ( o ) ;
}
}
void build () {
__build ( , , N ) ;
} void _modify ( const int o , const int L , const int R ) {
if ( R - L == ) maxv [ o ] = sumv [ o ] = v ;
else {
const int M = ( L + R ) / ;
if ( l < M ) _modify ( o << , L , M ) ;
else _modify ( o << | , M , R ) ;
maintain ( o ) ;
}
}
void modify ( const int p , const int V ) {
l = p ; v = V ; _modify ( , , N ) ;
} void _Qmax ( const int o , const int L , const int R ) {
if ( l <= L && R <= r ) max_equal ( v , maxv [ o ] ) ;
else {
const int M = ( L + R ) / ;
if ( l < M ) _Qmax ( o << , L , M ) ;
if ( M < r ) _Qmax ( o << | , M , R ) ;
}
}
int Qmax ( int L , int R ) {
if ( L > R ) swap ( L , R ) ;
l = L ; r = R + ; v = - ( << ) /* -INF */ ;
_Qmax ( , , N ) ;
return v ;
} void _Qsum ( const int o , const int L , const int R ) {
if ( l <= L && R <= r ) v += sumv [ o ] ;
else {
const int M = ( L + R ) / ;
if ( l < M ) _Qsum ( o << , L , M ) ;
if ( M < r ) _Qsum ( o << | , M , R ) ;
}
}
int Qsum ( int L , int R ) {
if ( L > R ) swap ( L , R ) ;
l = L ; r = R + ; v = ;
_Qsum ( , , N ) ;
return v ;
} } struct edge {
int p ;
edge * nxt ;
} ;
edge * V [ MAXN ] ;
int value [ MAXN ] ;
edge E [ MAXN * ] ; void ___add_edge ( const int a , const int b ) {
static edge * t = E ;
t -> p = b ; t -> nxt = V [ a ] ; V [ a ] = t ++ ;
}
void add_edge ( const int a , const int b ) {
___add_edge ( a , b ) ;
___add_edge ( b , a ) ;
} namespace Link_cut { int top [ MAXN ] ;
int num [ MAXN ] ;
int size [ MAXN ] ;
int height [ MAXN ] ;
int father [ MAXN ] ; namespace GET_SIZE {
int dfs ( const int o ) {
size [ o ] = ;
for ( edge * i = V [ o ] ; i != ; i = i -> nxt )
if ( i -> p != father [ o ] ) {
father [ i -> p ] = o ;
size [ o ] += dfs ( i -> p ) ;
}
return size [ o ] ;
}
}
void Get_size () { father [ ] = ; GET_SIZE :: dfs ( ) ; } namespace LINK_CUT {
void dfs ( const int o , const int t , const int h ) {
if ( o < ) return ;
else {
static int dfs_clock = ;
top [ o ] = t ;
num [ o ] = dfs_clock ++ ;
height [ o ] = h ;
int max_size_value = - , max_size_node = - ;
for ( edge * i = V [ o ] ; i != ; i = i -> nxt )
if ( i -> p != father [ o ] && max_size_value < size [ i -> p ] ) {
max_size_value = size [ i -> p ] ;
max_size_node = i -> p ;
}
dfs ( max_size_node , t , h ) ;
for ( edge * i = V [ o ] ; i != ; i = i -> nxt )
if ( i -> p != father [ o ] && i -> p != max_size_node ) dfs ( i -> p , i -> p , h + ) ;
}
}
} void cut_link ( ) {
LINK_CUT :: dfs ( , , ) ;
for ( int i = ; i < N ; ++ i ) Seg :: value [ num [ i ] ] = :: value [ i ] ;
Seg :: build () ;
} void modify ( const int p , const int v ) {
Seg :: modify ( num [ p ] , v ) ;
} int Qsum ( int a , int b ) {
int v = ;
while ( top [ a ] != top [ b ] ) {
if ( height [ a ] < height [ b ] ) swap ( a , b ) ;
v += Seg :: Qsum ( num [ a ] , num [ top [ a ] ] ) ;
a = father [ top [ a ] ] ;
}
v += Seg :: Qsum ( num [ a ] , num [ b ] ) ;
return v ;
} int Qmax ( int a , int b ) {
int v = -( << ) ;
while ( top [ a ] != top [ b ] ) {
if ( height [ a ] < height [ b ] ) swap ( a , b ) ;
max_equal ( v , Seg :: Qmax ( num [ a ] , num [ top [ a ] ] ) ) ;
a = father [ top [ a ] ] ;
}
max_equal ( v , Seg :: Qmax ( num [ a ] , num [ b ] ) ) ;
return v ;
} } char c [ ] ;
int main () {
scanf ( "%d" , & N ) ;
for ( int i = ; i < N ; ++ i ) {
int a , b ;
scanf ( "%d%d" , & a , & b ) ;
add_edge ( a - , b - ) ;
}
for ( int i = ; i < N ; ++ i ) scanf ( "%d" , & value [ i ] ) ;
Link_cut :: Get_size () ;
Link_cut :: cut_link () ; scanf ( "%d" , & Q ) ;
for ( int i = ; i < Q ; ++ i ) {
int a , b ;
scanf ( "%s%d%d" , c , & a , & b ) ;
switch ( c [ ] ) {
case 'H' :
Link_cut :: modify ( a - , b ) ;
break ;
case 'M' :
printf ( "%d\n" , Link_cut :: Qmax ( a - , b - ) ) ;
break ;
case 'S' :
printf ( "%d\n" , Link_cut :: Qsum ( a - , b - ) ) ;
break ;
}
} return ;
}

本博客禁止转载,转载请先联系作者,谢谢。

原地址:http://www.cnblogs.com/Christopher-Cao/p/5186126.html

如发现与文章与地址不同,请通过博客联系作者

bzoj1036 树的统计Count的更多相关文章

  1. BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)

    潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...

  2. BZOJ1036——树的统计count

    1.题目大意:给你一棵树,有三种操作 1>qmax,询问u到v中间点权的最大值 2>qsum,询问u到v中间点权和 3>change,把u这个节点的权值改为v 2.分析:树链剖分的裸 ...

  3. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

    [BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...

  4. [BZOJ1036][ZJOI2008]树的统计Count 解题报告|树链剖分

    树链剖分 简单来说就是数据结构在树上的应用.常用的为线段树splay等.(可现在splay还不会敲囧) 重链剖分: 将树上的边分成轻链和重链. 重边为每个节点到它子树最大的儿子的边,其余为轻边. 设( ...

  5. bzoj1036 [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 12646  Solved: 5085 [Subm ...

  6. bzoj1036 [ZJOI2008]树的统计Count 树链剖分模板题

    [ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ...

  7. bzoj千题计划124:bzoj1036: [ZJOI2008]树的统计Count

    http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分板子题 #include<cstdio> #include<iost ...

  8. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  9. BZOJ 1036: [ZJOI2008]树的统计Count

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 14354  Solved: 5802 [Subm ...

随机推荐

  1. Oracle ->> 层级查询语句(hierarchical query)connect by

    Oracle中的Connect By... Start With语句实现了递归查询或者树状查询. Connect By Prior 一方为起始(root)的ID 参考: http://www.360d ...

  2. 从一个前端项目实践 Git flow 的流程与参考

    Git flow 出自 A successful Git branching model,这里使用了一个前端项目配合本文稿实施了 git flow 并记录流程作出示例和参考,对 hotfix 与持续部 ...

  3. 基于webpivottable做的透视表

    1.绑定数据和配置: var wptConfig=<%= wptConfig%>; webPivotTable.setCsvData(<%=dataFields %>, < ...

  4. Android 的 init.rc 文件简介【转】

    转自:http://blog.csdn.net/yimiyangguang1314/article/details/6268177 init.rc由许多的Action和Service组成.每一个语句占 ...

  5. Docker入门命令

    Edit Docker入门命令 # 安装镜像sudo docker pull ubuntu:12.04# 镜像列表sudo docker images# 运行镜像sudo docker run -t ...

  6. Android Touch(2)View.OnTouchEvent与View.OnTouchListener区别

    1,在官方文档 docs/reference/android/view/View.OnTouchListener.html 中对OnTouchListener的描述 Interface definit ...

  7. 35.3wCF编程

    1.新建一个空白的解决方案文件,然后添加新建项目,项目类型为WCF服务应用程序,CH35Ex01 2.添加新建控制台应用程序Ch35Ex01Client 3.生成解决方案 4.右键Ch35Ex01Cl ...

  8. android 使用代码实现 RelativeLayout布局

    只需把代码copy进入oncreate方法即可运行 RelativeLayout rl = new RelativeLayout(this); Button btn1 = new Button(thi ...

  9. Java面向对象编程概述

    一. 01.软件开发经历周期: 软件分析:分析问题领域,了解客户的需求 软件设计:确定软件的总体结构,把整个软件系统划分为大大小小的多个子系统,设计每个子系统的具体结构 软件编码:用选定的编程语言来编 ...

  10. UVa 10048 Audiophobia【Floyd】

    题意:给出一个c个点,s条边组成的无向图,求一点到另一点的路径上最大权值最小的路径,输出这个值 可以将这个 d[i][j]=min(d[i][j],d[i][k]+d[k][j]) 改成 d[i][j ...