bzoj1036 count 树链剖分或LCT
这道题很久以前用树链剖分写的,最近在学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的更多相关文章
- Bzoj 1036: [ZJOI2008]树的统计Count  树链剖分,LCT
		1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 11102 Solved: 4490[Submit ... 
- 【BZOJ1036】树的统计Count(树链剖分,LCT)
		题意:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: ... 
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
		[BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ... 
- Cogs 1688. [ZJOI2008]树的统计Count(树链剖分+线段树||LCT)
		[ZJOI2008]树的统计Count ★★★ 输入文件:bzoj_1036.in 输出文件:bzoj_1036.out 简单对比 时间限制:5 s 内存限制:162 MB [题目描述] 一棵树上有n ... 
- bzoj1036  [ZJOI2008]树的统计Count 树链剖分模板题
		[ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u ... 
- BZOJ1036 [ZJOI2008]树的统计Count 树链剖分
		欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1036 题意概括 一个树,每个节点有一个权值.3种操作. 1:修改某一个节点的权值. 2:询问某两个 ... 
- 【bzoj1036】[ZJOI2008]树的统计Count 树链剖分+线段树
		题目描述 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v ... 
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
		1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ... 
- BZOJ 1036: [ZJOI2008]树的统计Count( 树链剖分 )
		树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ... 
随机推荐
- Go语言 8 反射
			文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 8.1概念和作用 Reflection(反射)在计算 ... 
- spring-boot 更换依赖版本
			创建Spring Boot操作步骤如下: 在File菜单里面选择 New > Project,然后选择Spring Initializr 更换版本 或 pom spring-boot-start ... 
- bugku数字验证绕过正则
			题目:http://120.24.86.145:9009/21.php 第6行使用正则匹配如果匹配到$password开头12个字符中有空格则输出flag并执行exit; 12行是正则匹配$passw ... 
- Python3  多进程
			多进程(multiprocessing)的用法和多线程(threading)类似,里面的函数也一样,start()为启动函数,join() 等待该进程运行结束,每一个进程也是由它的父进程产生 1.简单 ... 
- javaScript-继承2种方式
			1.组合继承 组合继承带来的问题很明细就是父类的构造函数会调用两次,如: function Person(name, age, sex) { this.name = name; this.age = ... 
- python 内置函数eval()、exec()、compile()
			eval 函数的作用: 计算指定表达式的值.也就是说它要执行的python代码只能是单个表达式,而不是复杂的代码逻辑. eval(source, globals=None, locals=Non ... 
- js中startWith、endWith 函数不能在任何浏览器兼容的问题
			在做js测试的时候用到了startsWith函数,但是他并不是每个浏览器都有的,所以我们一般要重写一下这个函数,具体的用法可以稍微总结一下 在有些浏览器中他是undefined 所以我们可以这样的处理 ... 
- Linux 基础——权限管理命令chown、chgrp
			一.chown命令与chgrp命令的作用 有时你需要改变文件或目录的属主,比如有人离职或开发人员创建了一个在测试或生产环境中需要归属在系统账户下的应用.Linux提供了两个命令来实现这个功能:chow ... 
- 号外,号外 -几乎所有的binary search和mergesort都有错
			号外,号外 -几乎所有的binary search和mergesort都有错 这是Joshua Bloch(Effective Java的作者)在google blog上发的帖子.在说这个帖子之前,不 ... 
- 小甲鱼Python笔记(上)
			基于Python 3.4.3 一 二 三 四 基础 print 三版必须加括号,二版不用加 alt + n :上一条语句 alt + p :下一条语句 打印三条hello 没有大括号,用缩进来表示 ... 
