这道题很久以前用树链剖分写的,最近在学LCT ,就用LCT再写了一遍,也有一些收获。

因为这道题点权可以是负数,所以在update时就要注意一下,因为平时我的0节点表示空,它的点权为0,这样可以处理点权为非负求最大值和求和的情况(即不用特判某个点是否有左右儿子,直接更新就行了),但这道题就不行(求和要求它为0,求最大值要求它为-oo)。所以就必须特判~~~~

综上:若0号节点存在一个不可能成为答案(在求最大值时是-oo,求最小值时是+oo)或对答案没有贡献的值(在求和时是0)时,初始化时将0节点的权值设为该值,更新时就可以不用特判某个点是否为0。否则引用左右儿子值时就必须特判某个节点是否有左右儿子。

LCT用的时间大概是树链剖分的两倍。

树链剖分:

 /**************************************************************
Problem: 1036
User: idy002
Language: C++
Result: Accepted
Time:2880 ms
Memory:5116 kb
****************************************************************/ #include <cstdio>
#include <vector>
#define lson rt<<1
#define rson rt<<1|1
#define inf 300000000
#define maxn 30001
using namespace std; int n;
vector<int> g[maxn];
int wght[maxn], siz[maxn], son[maxn], pre[maxn], dep[maxn], top[maxn], vid[maxn], vcnt;
int smax[maxn<<], ssum[maxn<<]; void up_sum( int pos, int v, int rt, int l, int r ) {
if( l==r ) {
ssum[rt] = v;
return;
}
int mid=(l+r)>>;
if( mid>=pos ) up_sum( pos, v, lson, l, mid );
else up_sum( pos, v, rson, mid+, r );
ssum[rt] = ssum[lson] + ssum[rson];
}
void up_max( int pos, int v, int rt, int l, int r ) {
if( l==r ) {
smax[rt] = v;
return;
}
int mid=(l+r)>>;
if( mid>=pos ) up_max( pos, v, lson, l, mid );
else up_max( pos, v, rson, mid+, r );
smax[rt] = max( smax[lson], smax[rson] );
}
int qu_sum( int L, int R, int rt, int l, int r ) {
if( L<=l && r<=R ) return ssum[rt];
int mid=(l+r)>>, re=;
if( mid>=L ) re+=qu_sum(L,R,lson,l,mid);
if( mid+<=R ) re+=qu_sum(L,R,rson,mid+,r);
return re;
}
int qu_max( int L, int R, int rt, int l, int r ) {
if( L<=l && r<=R ) return smax[rt];
int mid=(l+r)>>, re=-inf;
if( mid>=L ) re = qu_max( L,R,lson,l,mid);
if( mid+<=R ) re = max( re, qu_max( L,R,rson,mid+,r ) );
return re;
}
void dfs1( int u ) {
siz[u] = , son[u] = ;
for( int t=; t<(int)g[u].size(); t++ ) {
int v=g[u][t];
if( v==pre[u] ) continue;
pre[v] = u;
dep[v] = dep[u]+;
dfs1(v);
siz[u] += siz[v];
son[u] = siz[v]>siz[son[u]] ? v : son[u];
}
}
void dfs2( int u, int tp ) {
vid[u] = ++vcnt, top[u] = tp;
if( son[u] ) dfs2(son[u],tp);
for( int t=; t<(int)g[u].size(); t++ ) {
int v=g[u][t];
if( v==pre[u] || v==son[u] ) continue;
dfs2(v,v);
}
}
void build() {
pre[] = , dep[] = ;
dfs1();
vcnt = ;
dfs2(,);
for( int i=; i<=n; i++ ) {
up_sum( vid[i], wght[i], , , vcnt );
up_max( vid[i], wght[i], , , vcnt );
}
}
void update( int v, int val ) {
up_sum( vid[v], val, , , vcnt );
up_max( vid[v], val, , , vcnt );
}
int query_sum( int u, int v ) {
int r=;
while( top[u]!=top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
r += qu_sum( vid[top[u]], vid[u], , , vcnt );
u = pre[top[u]];
}
if( u==v ) return r+qu_sum(vid[u],vid[v],,,vcnt);
if( dep[u]<dep[v] ) swap(u,v);
r += qu_sum( vid[v], vid[u], , , vcnt );
return r;
}
int query_max( int u, int v ) {
int r=-inf;
while( top[u]!=top[v] ) {
if( dep[top[u]]<dep[top[v]] ) swap(u,v);
r = max( r, qu_max( vid[top[u]], vid[u], , , vcnt ) );
u = pre[top[u]];
}
if( u==v ) return max( r, qu_max( vid[u], vid[v], , , vcnt ) );
if( dep[u]<dep[v] ) swap(u,v);
r = max( r, qu_max( vid[v], vid[u], , , vcnt ) );
return r;
}
void answer() {
int q, a, b;
scanf( "%d", &q );
while(q--) {
char dir[];
scanf( "%s%d%d", dir, &a, &b );
if( dir[]=='C' )
update(a,b);
else if( dir[]=='S' )
printf( "%d\n", query_sum(a,b) );
else
printf( "%d\n", query_max(a,b) );
}
}
void input() {
scanf( "%d", &n );
for( int i=,u,v; i<n; i++ ) {
scanf( "%d%d", &u, &v );
g[u].push_back(v);
g[v].push_back(u);
}
for( int i=; i<=n; i++ )
scanf( "%d", wght+i );
}
int main() {
input();
build();
answer();
}

LCT:

 /**************************************************************
Problem: 1036
User: idy002
Language: C++
Result: Accepted
Time:5816 ms
Memory:2932 kb
****************************************************************/ #include <cstdio>
#include <iostream>
#define maxn 30010
#define oo 0x3f3f3f3f
using namespace std; namespace L {
int pnt[maxn], pre[maxn], son[maxn][], val[maxn], mxv[maxn], sum[maxn], rtg[maxn]; void update( int u ) {
mxv[u] = sum[u] = val[u];
int ls = son[u][], rs = son[u][];
if(ls) {
mxv[u] = max( mxv[u], mxv[ls] );
sum[u] += sum[ls];
}
if(rs) {
mxv[u] = max( mxv[u], mxv[rs] );
sum[u] += sum[rs];
}
}
void rotate( int u, int d ) {
int p = pre[u];
int s = son[u][!d];
int ss = son[s][d];
son[u][!d] = ss;
son[s][d] = u;
if( p ) son[p][ u==son[p][] ] = s;
else pnt[s] = pnt[u];
pre[u] = s;
pre[ss] = u;
pre[s] = p;
update( u );
update( s );
}
void pushdown( int u ) {
if( rtg[u] ) {
int &ls = son[u][], &rs = son[u][];
swap( ls, rs );
rtg[ls] ^= ;
rtg[rs] ^= ;
rtg[u] = ;
}
}
void big_push( int u ) {
if( pre[u] ) big_push(pre[u]);
pushdown( u );
}
void splay( int u, int top= ) {
big_push( u );
while( pre[u]!=top ) {
int p = pre[u];
int nl = u==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
void access( int nd ) {
int u = nd;
int v = ;
while( u ) {
splay( u );
int s = son[u][];
pre[s] = ;
pnt[s] = u;
pre[v] = u;
son[u][] = v;
update(u);
v = u;
u = pnt[u];
}
splay( nd );
}
int findroot( int u ) {
while( pre[u] ) u = pre[u];
while( pnt[u] ) {
u = pnt[u];
while( pre[u] ) u = pre[u];
}
return u;
}
void makeroot( int u ) {
access( u );
rtg[u] ^= ;
}
void link( int u, int v ) {
makeroot( u );
makeroot( v );
pnt[u] = v;
}
void up_val( int u, int w ) {
splay( u );
val[u] = w;
update( u );
}
int qu_max( int u, int v ) {
makeroot( u );
access( v );
if( son[v][] ) return max( val[v], mxv[son[v][]] );
else return val[v];
}
int qu_sum( int u, int v ) {
makeroot( u );
access( v );
if( son[v][] ) return val[v] + sum[son[v][]];
else return val[v];
}
}; int n, q; int main() {
scanf( "%d", &n );
for( int i=,u,v; i<=n; i++ ) {
scanf( "%d%d", &u, &v );
L::link(u,v);
}
for( int i=,w; i<=n; i++ ) {
scanf( "%d", &w );
L::up_val(i,w);
}
scanf( "%d", &q );
while( q-- ) {
char ch[];
int u, v, w;
scanf( "%s", ch );
if( ch[]=='C' ) {
scanf( "%d%d", &u, &w );
L::up_val( u, w );
} else if( ch[]=='M' ) {
scanf( "%d%d", &u, &v );
printf( "%d\n", L::qu_max( u, v ) );
} else {
scanf( "%d%d", &u, &v );
printf( "%d\n", L::qu_sum( u, v ) );
}
}
}

bzoj1036 count 树链剖分或LCT的更多相关文章

  1. Bzoj 1036: [ZJOI2008]树的统计Count 树链剖分,LCT

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

  2. 【BZOJ1036】树的统计Count(树链剖分,LCT)

    题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: ...

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

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

  4. Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)

    [ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ...

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

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

  6. BZOJ1036 [ZJOI2008]树的统计Count 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1036 题意概括 一个树,每个节点有一个权值.3种操作. 1:修改某一个节点的权值. 2:询问某两个 ...

  7. 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树

    题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ...

  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( 树链剖分 )

    树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...

随机推荐

  1. Paramiko使用

    1.下载安装 pycrypto-2.6.1.tar.gz (apt-get install python-dev) 解压,进入,python setup.py build[编译],python set ...

  2. 使用showplan.sql分析sql Performance

    在HelloDBA网站找到一个分析sql性能的工具-showplan,记录一下 showplan.sql下载路径:http://www.HelloDBA.com/Download/showplan.z ...

  3. UBIFS学习笔记

    在做项目的时候,发现flash芯片有异常现象,经过打印分析,发现是UBIFS方面设置有一些问题,经过查阅一部分资料,最终得到问题的答案. 在解决问题的过程中,发现打印信息比较重要,但网上并没有直接的相 ...

  4. rabbitmq和kafka怎么选?【转】

    MQ框架非常之多,今天简单说一下有代表性的两个MQ(rabbitmq和kafka).经常会有人问rabbitmq和kafka到底哪个好呢?其实没有好与不好之分,只有哪个更合适,首先要根据自己项目的业务 ...

  5. Codeforces Round #441 (Div. 2)

    Codeforces Round #441 (Div. 2) A. Trip For Meal 题目描述:给出\(3\)个点,以及任意两个点之间的距离,求从\(1\)个点出发,再走\(n-1\)个点的 ...

  6. springboot + swagger2 生成api文档

    直接贴代码: <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  7. VS里属性窗口中的生成操作释义

    生成操作:无,编译 ,内容 ,嵌入的资源... 如果是类.cs文件,就得编译之后你才能使用的.如果是txt,excel 这种文件,就属性内容或者资源文件了. 内容(Content) - 不编译该文件, ...

  8. CentOS系统yum源配置修改、yum安装软件包源码包出错解决办法apt.sw.be couldn't connect to host

    yum安装包时报错: Could not retrieve mirrorlist http://mirrorlist.repoforge.org/el6/mirrors-rpmforge error  ...

  9. Android项目包命名规则是怎样的?

    com.example.app.activity | Activity 类com.example.app.widget | 自定义的小UIcom.example.app.db | 数据库相关操作com ...

  10. IEEEXtreme 10.0 - Dog Walking

    博客中的文章均为 meelo 原创,请务必以链接形式注明 本文地址 Xtreme 10.0 - Dog Walking 题目来源 第10届IEEE极限编程大赛 https://www.hackerra ...