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( 树链剖分 )
树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...
随机推荐
- 深入理解Spring系列之三:BeanFactory解析
转载 https://mp.weixin.qq.com/s?__biz=MzI0NjUxNTY5Nw==&mid=2247483824&idx=1&sn=9b7c2603093 ...
- 【swupdate文档 四】SWUpdate:使用默认解析器的语法和标记
SWUpdate:使用默认解析器的语法和标记 介绍 SWUpdate使用库"libconfig"作为镜像描述的默认解析器. 但是,可以扩展SWUpdate并添加一个自己的解析器, ...
- ab的使用方法【转】
使用方法 ab -n 800 -c 800 http://192.168.0.10/ (-n发出800个请求,-c模拟800并发,相当800人同时访问,后面是测试url) ab -t 60 -c 1 ...
- 大数据系列之分布式数据库HBase-1.2.4+Zookeeper 安装及增删改查实践
之前介绍过关于HBase 0.9.8版本的部署及使用,本篇介绍下最新版本HBase1.2.4的部署及使用,有部分区别,详见如下: 1. 环境准备: 1.需要在Hadoop[hadoop-2.7.3] ...
- Python os模块和sys模块 操作系统的各种接口
一.os模块 这个模块提供了一个便携式去使用操作系统的相关功能,如果只是想操作路径,请参阅os.path模块. ''' os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 ...
- [ python ] FTP作业进阶
作业:开发一个支持多用户在线的FTP程序 要求: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp se ...
- 数据库连接池(c3p0与druid)
1.数据库连接池概念 其实就是一个容器(集合),存放数据库连接的容器.当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归 ...
- 非常粗糙的react网页ppt
import React, {Component} from 'react'; import './slide.css'; class Page extends Component { constru ...
- [你必须知道的.NET]第十九回:对象创建始末(下)
本文将介绍以下内容: 对象的创建过程 内存分配分析 内存布局研究 接上回[第十八回:对象创建始末(上)],继续对对象创建话题的讨论>>> 2.2 托管堆的内存分配机制 引用类型的实例 ...
- 【PAT】1012. 数字分类 (20)
1012. 数字分类 (20) 给定一系列正整数,请按要求对数字进行分类,并输出以下5个数字: A1 = 能被5整除的数字中所有偶数的和: A2 = 将被5除后余1的数字按给出顺序进行交错求和,即计算 ...