标签:
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