标签:
| Time Limit: 4000MS | Memory Limit: 65536K | |
| Total Submissions: 6898 | Accepted: 1742 |
Description
Input
Output
Sample Input
3 3 1 1 2 1 2 3 2 0 2 1 2 3 0 3
Sample Output
1 3
树链剖分的模板题,做好线段树后,就是简单的单点更新,区域查询了
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define maxn 110000
#define lmin 1
#define rmax n
#define root lmin,rmax,1
#define lson l,(l+r)/2,rt<<1
#define rson (l+r)/2+1,r,rt<<1|1
#define now l,r,rt
#define int_now int l,int r,int rt
struct node
{
int u , v , w ;
int next ;
} edge[maxn<<1];
int head[maxn] , vis[maxn] , cnt ;//存储树,vis标记节点
int belong[maxn] ;//记录第i条边(u,v)中的子节点v
int p[maxn] ;//子节点为v的树枝的长度
int cl[maxn<<2] , s[maxn] ;//线段树数组cl,s记录标号为1到n的树杈的值,提供给cl建立线段树
int num[maxn] ;//以节点u为根的子树的节点个数
int dep[maxn] ;//节点u的深度,根的深度为1
int top[maxn] ;//u所在的重链的最顶端的节点
int son[maxn] , fa[maxn] ;//u的重儿子节点,u的父亲节点,
int w[maxn] , step ;//记录节点v与父亲的连边在线段树的位置
int n , m , t ;
void add(int u,int v,int w)
{
edge[cnt].u = u ;
edge[cnt].v = v ;
edge[cnt].w = w ;
edge[cnt].next = head[u] ;
head[u] = cnt++ ;
edge[cnt].u = v ;
edge[cnt].v = u ;
edge[cnt].w = w ;
edge[cnt].next = head[v] ;
head[v] = cnt++ ;
return ;
}
void dfs1(int u)
{
int i , v , max1 = -1 , k = -1 ;
num[u] = 1 ;
for(i = head[u] ; i != -1 ; i = edge[i].next)
{
v = edge[i].v ;
if( vis[v] ) continue ;
belong[i/2+1] = v ;
vis[v] = 1 ;
dep[v] = dep[u] + 1 ;
fa[v] = u ;
p[v] = edge[i].w ;
dfs1(v) ;
if( num[v] > max1 )
{
max1 = num[v] ;
k = v ;
}
}
son[u] = k ;
return ;
}
void dfs2(int u)
{
if( son[u] == -1 ) return ;
int i , v = son[u] ;
vis[v] = 1 ;
w[v] = step ;
s[step++] = p[v] ;
top[v] = top[u] ;
dfs2(v) ;
for(i = head[u] ; i != -1 ; i = edge[i].next)
{
v = edge[i].v ;
if( vis[v] ) continue ;
vis[v] = 1 ;
w[v] = step ;
s[step++] = p[v] ;
top[v] = v ;
dfs2(v) ;
}
return ;
}
void dfs()
{
memset(vis,0,sizeof(vis)) ;
vis[1] = 1 ;
dep[1] = 1 ;
fa[1] = -1 ;
dfs1(1) ;
memset(vis,0,sizeof(vis)) ;
vis[1] = 1 ;
step = 1 ;
top[1] = 1 ;
dfs2(1) ;
return ;
}
void push_up(int_now)
{
cl[rt] = cl[rt<<1] + cl[rt<<1|1] ;
return ;
}
void build(int_now)
{
cl[rt] = 0 ;
if( l != r )
{
build(lson) ;
build(rson) ;
push_up(now) ;
}
else
cl[rt] = s[l] ;
return ;
}
void update(int in,int x,int_now)
{
if( l == in && r == in )
{
cl[rt] = x ;
return ;
}
if( in <= (l+r)/2 )
update(in,x,lson) ;
else
update(in,x,rson) ;
push_up(now) ;
return ;
}
int query(int ll,int rr,int_now)
{
if( ll > r || rr < l ) return 0;
if( ll <= l && rr >= r ) return cl[rt] ;
return query(ll,rr,lson)+query(ll,rr,rson) ;
}
void solve(int u,int v)
{
int temp , f1 , f2 , ans = 0 ;
while( u != v )
{
if( dep[u] < dep[v] )
{
temp = u ;
u = v ;
v = temp ;
}
f1 = top[u] ;
f2 = top[v] ;
if( f1 == f2 )
{
ans += query(w[son[v]],w[u],root) ;
v = u ;
}
else if( dep[f1] >= dep[f2] )
{
ans += query(w[f1],w[u],root) ;
u = fa[f1] ;
}
else
{
ans += query(w[f2],w[v],root) ;
v = fa[f2] ;
}
}
printf("%d\n", ans) ;
return ;
}
int main()
{
int i , j , k ;
int u , v ;
while( scanf("%d %d %d", &n, &m, &t) != EOF )
{
cnt = 0 ;
memset(head,-1,sizeof(head)) ;
for(i = 1 ; i < n ; i++)
{
scanf("%d %d %d", &u, &v, &k) ;
add(u,v,k) ;
}
dfs() ;
n-- ;
build(root) ;
i = t ;
while( m-- )
{
scanf("%d", &k) ;
if( k == 0 )
{
scanf("%d", &j) ;
solve(i,j) ;
i = j ;
}
else
{
scanf("%d %d", &j, &k) ;
v = belong[j] ;
update(w[v],k,root) ;
}
}
}
return 0 ;
}
poj2763--Housewife Wind(树链剖分+线段树)
标签:
原文地址:http://blog.csdn.net/winddreams/article/details/45094105