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( 树链剖分 )
树链剖分... 不知道为什么跑这么慢 = = 调了一节课啊跪.. ------------------------------------------------------------------- ...
随机推荐
- 将neuroph导入到Eclipse中
1.下载neuroph 网址:http://neuroph.sourceforge.net/ 本人选择的是2.8版本 2.解压文件 本人解压至:D:\neuroph-2.8 3.neuroph jar ...
- LDA线性判别分析
LDA线性判别分析 给定训练集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能的近,异类样例点尽可能的远,对新样本进行分类的时候,将新样本同样的投影,再根据投影得到的位置进行判断,这个新样本的 ...
- RTC
RTC的英文全称是Real-Time Clock,翻译过来是实时时钟芯片. RTC是PC主板上的晶振及相关电路组成的时钟电路的生成脉冲主板上的晶振及相关电路组成的时钟电路的生成脉冲,,RTC经过825 ...
- HTTP 请求 的方法Util
HTTP请求 的一系列方法总结 /** * *******************************传统请求--开始************************************** ...
- Spring Cloud Feign 在调用接口类上,配置熔断 fallback后,输出异常
Spring Cloud Feign 在调用接口类上,配置熔断 fallback后,出现请求异常时,会进入熔断处理,但是不会抛出异常信息. 经过以下配置,可以抛出异常: 将原有ErrorEncoder ...
- booklist for machine learning
Recommended Books Here is a list of books which I have read and feel it is worth recommending to fri ...
- logstash参数配置
input配置: file:读取文件 input { file{ path => ["/var/log/*.log","/var/log/message" ...
- Ubuntu16.4 修改静态ip地址
root@temple-102:~# ifconfig eno1 Link encap:Ethernet HWaddr 0c:c4:7a:e6:49:74 UP BROADCAST MULTICAST ...
- Windows Azure 初体验
最近看到windows azure 在做活动,只需花一块钱就可以体验一个月的windows azure. 于是,我就注册了一个账号也尝试一把云时代,传送门. 注册很简单的,成功后可以看到这个界面. 然 ...
- Wannafly挑战赛18 C - 异或和
思路:我刚开始是想旋转四次坐标,每次用bit计算每个点左上角的点到这个点的距离,TLE了.... 这种算曼哈顿距离的可以将x 轴和 y 轴独立开来,分别计算. #include<bits/std ...