bzoj 1036 Tree Count

题目大意:给出一棵树,每个点有一个权值,要求三种操作:1.修改某个点的权值,2.询问x到y路径上各点的权值最大值,3.询问x到y路径上各点的权值之和。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 #define N 30010
  7 #define ls o<<1
  8 #define rs o<<1|1
  9 #define define_m int m=(l+r)>>1
 10
 11 int first[N] , k;
 12 struct Edge{
 13     int y , next;
 14 }e[N<<1];
 15
 16 void add_edge(int x , int y)
 17 {
 18     e[k].y = y , e[k].next = first[x];
 19     first[x] = k++;
 20 }
 21
 22 int sz[N] , dep[N] , fa[N] , son[N] , top[N] , id[N] , num;
 23 void dfs(int u , int f , int d)
 24 {
 25     fa[u] = f , sz[u] = 1 , dep[u]= d , son[u]=0;
 26     int mx = 0;
 27     for(int i=first[u] ; ~i ; i=e[i].next){
 28         int v = e[i].y;
 29         if(v == f) continue;
 30         dfs(v , u , d+1);
 31         sz[u]+=sz[v];
 32         if(sz[v]>mx) mx=sz[v] , son[u]=v;
 33     }
 34 }
 35
 36 void dfs1(int u , int f , int head)
 37 {
 38     top[u]=head , id[u]=++num;
 39     if(son[u]) dfs1(son[u] , u , head);
 40     for(int i=first[u] ; ~i ; i=e[i].next){
 41         int v = e[i].y;
 42         if(v == f || v == son[u]) continue;
 43         dfs1(v , u , v);
 44     }
 45 }
 46
 47 int sum[N<<2] , mx[N<<2] , val[N];
 48 void push_up(int o)
 49 {
 50     sum[o] = sum[ls]+sum[rs];
 51     mx[o] = max(mx[ls] , mx[rs]);
 52 }
 53
 54 void build(int o , int l , int r)
 55 {
 56     if(l==r){
 57         sum[o]=mx[o]=val[l];
 58         return ;
 59     }
 60     define_m;
 61     build(ls , l , m);
 62     build(rs , m+1 , r);
 63     push_up(o);
 64 }
 65
 66 void update(int o , int l , int r , int p , int v)
 67 {
 68     if(l==r){
 69         sum[o]=mx[o]=v;
 70         return;
 71     }
 72     define_m;
 73     if(m>=p) update(ls , l , m , p , v);
 74     else update(rs , m+1 , r , p , v);
 75     push_up(o);
 76 }
 77
 78 int qSum(int o , int l , int r , int s , int t)
 79 {
 80     if(l>=s && r<=t) return sum[o];
 81     define_m;
 82     int res = 0;
 83     if(m>=s) res+=qSum(ls , l , m , s , t);
 84     if(m<t) res+=qSum(rs , m+1 , r , s , t);
 85     return res;
 86 }
 87
 88 int qMax(int o , int l , int r , int s , int t)
 89 {
 90     if(l>=s && r<=t) return mx[o];
 91     define_m;
 92     int res = -1e9;
 93     if(m>=s) res = max(res , qMax(ls , l , m , s , t));
 94     if(m<t) res = max(res , qMax(rs , m+1 , r , s , t));
 95     return res;
 96 }
 97
 98 int calPath(int u , int v , int flag)
 99 {
100     int top1 = top[u] , top2 = top[v] , ret=-1e9;
101     if(flag) ret=0;
102     while(top1!=top2){
103         if(dep[top1]<dep[top2]){
104             swap(top1 , top2);
105             swap(u , v);
106         }
107         if(flag) ret+=qSum(1 , 1 , num , id[top1] , id[u]);
108         else ret=max(ret , qMax(1,1,num,id[top1] , id[u]));
109         u = fa[top1];
110         top1 = top[u];
111     }
112     if(dep[u]<dep[v]) swap(u,v);
113     if(flag) ret+=qSum(1,1,num,id[v],id[u]);
114     else ret=max(ret , qMax(1,1,num,id[v],id[u]));
115     return ret;
116 }
117 char str[8];
118 int main()
119 {
120     //freopen("in.txt" , "r" , stdin);
121     int n , x , y , q;
122     while(scanf("%d" , &n)!=EOF)
123     {
124         memset(first , -1 , sizeof(first));
125         k = 0;
126         for(int i=1 ; i<n ; i++){
127             scanf("%d%d" , &x , &y);
128             add_edge(x , y);
129             add_edge(y , x);
130         }
131         dfs(1 , 0 , 1);
132         num = 0;
133         dfs1(1 , 0 , 1);
134         int tmp[N];
135         for(int i=1 ; i<=n ; i++) scanf("%d" , val+i) , tmp[i]=val[i];
136         for(int i=1 ; i<=n ; i++) val[id[i]]=tmp[i];
137         build(1 , 1 , num);
138     //    for(int i=1 ; i<=7 ; i++) cout<<i<<" "<<mx[i]<<" "<<sum[i]<<endl;
139         scanf("%d" , &q);
140         while(q--){
141             scanf("%s%d%d", str , &x , &y);
142             if(str[0]==‘C‘){
143                 update(1 , 1 , num , id[x] , y);
144             }
145             else if(str[1]==‘M‘){
146                 int ret = calPath(x , y , 0);
147                 printf("%d\n" , ret);
148             }else{
149                 int ret = calPath(x , y , 1);
150                 printf("%d\n" , ret);
151             }
152         }
153     }
154     return 0;
155 }
时间: 2024-11-13 10:06:26

bzoj 1036 Tree Count的相关文章

[BZOJ 1036] [ZJOI2008] 树的统计Count 【Link Cut Tree】

题目链接:BZOJ - 1036 题目分析 这道题可以用树链剖分,块状树等多种方法解决,也可以使用 LCT. 修改某个点的值时,先将它 Splay 到它所在的 Splay 的根,然后修改它的值,再将它 Update 一下. 询问 x, y 两点之间的路径时,假设 x 是深度小的那一个,先 Access(x) ,然后再 Access(y) 的返回值就是 x, y 的 LCA . 这时从 x 到 LCA 的路径已经在 LCA 处断开了.我们将 x Splay 一下,然后就是 x 所在的 Splay,

【BZOJ 1036】树的统计Count(树链剖分)

[BZOJ 1036]树的统计Count(树链剖分) 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 12991  Solved: 5233 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成 一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权

BZOJ 1036 树链剖分模板题

BZOJ 1036 题意:一棵树,每个点有权值,三种操作:修改一个点的值:询问一条链上最大值:询问一条链上权值和. tags:模板题 // bzoj 1036 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define FF(i,a,b) for (int i=a;i<=b;i++) #define F(i,b,a)

BZOJ 1452: [JSOI2009]Count (二维树状数组)

Description Input Output Sample Input Sample Output 1 2 HINT 二维树状数组的简单应用,c数组的第一维坐标相当于哈希.如果是修改操作,修改前 将当前的值的个数以及祖先都减1, 修改后将个数加1. #include <iostream> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include

【BZOJ 1036】【ZJOI 2008】树的统计

此题为树链剖分的裸题. 代码如下,使用常用的轻重链剖分. /************************************************************** Problem: 1036 User: Evensgn Language: C++ Result: Accepted Time:2468 ms Memory:5772 kb ****************************************************************/ #inc

spoj 375 AND bzoj 1036 树链剖分

树链剖分的入门题目,自己写了下感觉还是挺好写的,不过真的有点长... spoj 375 边有权值: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int INF = -999999999; 7 const int N = 10001; 8 int head[N]; 9 int sz[N]; 10 int depth[N]; 1

BZOJ 1036: [ZJOI2008]树的统计Count (树链剖分模板题)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14982  Solved: 6081[Submit][Status][Discuss] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I

bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 10677  Solved: 4313[Submit][Status][Discuss] Description 一 棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

树链剖分教程 &amp; bzoj 1036 [ZJOI2008] 树的统计 Count 题解

转载请注明:http://blog.csdn.net/jiangshibiao/article/details/24669751 [原题] 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4465  Solved: 1858 [Submit][Status] Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I