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];
 11 int num[N];
 12 int top[N];
 13 int dfn[N];
 14 int hc[N];
 15 int fa[N];
 16 int n, e, dfs_clock;
 17
 18 void init()
 19 {
 20     e = dfs_clock = 0;
 21     memset( head, -1, sizeof(head) );
 22 }
 23
 24 struct Edge
 25 {
 26     int v, w, next;
 27 } edge[N << 1];
 28
 29 void addEdge( int u, int v, int w )
 30 {
 31     edge[e].v = v;
 32     edge[e].w = w;
 33     edge[e].next = head[u];
 34     head[u] = e++;
 35 }
 36
 37 void dfs1( int u, int pre, int dep )
 38 {
 39     sz[u] = 1;
 40     fa[u] = pre;
 41     depth[u] = dep;
 42     hc[u] = -1;
 43     for ( int i = head[u]; i != -1; i = edge[i].next )
 44     {
 45         int v = edge[i].v;
 46         if ( v == pre ) continue;
 47         dfs1( v, u, dep + 1 );
 48         sz[u] += sz[v];
 49         if ( hc[u] == -1 || sz[v] > sz[hc[u]] )
 50         {
 51             hc[u] = v;
 52         }
 53     }
 54 }
 55
 56 void dfs2( int u, int tp )
 57 {
 58     top[u] = tp;
 59     dfn[u] = ++dfs_clock;
 60     if ( hc[u] != -1 )
 61     {
 62         dfs2( hc[u], tp );
 63     }
 64     for ( int i = head[u]; i != -1; i = edge[i].next )
 65     {
 66         int v = edge[i].v;
 67         if ( v == fa[u] ) continue;
 68         if ( v == hc[u] )
 69         {
 70             num[dfn[v]] = edge[i].w;
 71         }
 72         else
 73         {
 74             dfs2( v, v );
 75             num[dfn[v]] = edge[i].w;
 76         }
 77     }
 78 }
 79
 80 struct Node
 81 {
 82     int l, r, maxn;
 83 } node[N << 2];
 84
 85 void pushup( int i )
 86 {
 87     node[i].maxn = max( node[i << 1].maxn, node[i << 1 | 1].maxn );
 88 }
 89
 90 void build( int i, int l, int r )
 91 {
 92     node[i].l = l, node[i].r = r;
 93     if ( l == r )
 94     {
 95         node[i].maxn = num[l];
 96         return ;
 97     }
 98     int mid = ( l + r ) >> 1;
 99     build( i << 1, l, mid );
100     build( i << 1 | 1, mid + 1, r );
101     pushup(i);
102 }
103
104 void update( int i, int pos, int val )
105 {
106     if ( node[i].l == pos && node[i].r == pos )
107     {
108         node[i].maxn = val;
109         return ;
110     }
111     int mid = ( node[i].l + node[i].r ) >> 1;
112     if ( pos <= mid )
113     {
114         update( i << 1, pos, val );
115     }
116     else
117     {
118         update( i << 1 | 1, pos, val );
119     }
120     pushup(i);
121 }
122
123 int query( int i, int l, int r )
124 {
125     if ( node[i].l == l && node[i].r == r )
126     {
127         return node[i].maxn;
128     }
129     int mid = ( node[i].l + node[i].r ) >> 1;
130     if ( r <= mid )
131     {
132         return query( i << 1, l, r );
133     }
134     else if ( l > mid )
135     {
136         return query( i << 1 | 1, l, r );
137     }
138     else
139     {
140         return max( query( i << 1, l, mid ), query( i << 1 | 1, mid + 1, r ) );
141     }
142 }
143
144 struct Data
145 {
146     int u, v;
147 } d[N];
148
149 int tree_query( int x, int y )
150 {
151     int ans = INF;
152     while ( top[x] != top[y] )
153     {
154         if ( depth[top[x]] < depth[top[y]] )
155         {
156             swap( x, y );
157         }
158         ans = max( ans, query( 1, dfn[top[x]], dfn[x] ) );
159         x = fa[top[x]];
160     }
161     if ( x != y )
162     {
163         if ( depth[x] > depth[y] ) swap( x, y );
164         ans = max( ans, query( 1, dfn[x] + 1, dfn[y] ) );
165     }
166     return ans;
167 }
168
169 void tree_update( int x, int y )
170 {
171     int u = d[x].u, v = d[x].v;
172     if ( depth[u] < depth[v] ) u = v;
173     update( 1, dfn[u], y );
174 }
175
176 int main ()
177 {
178     int t;
179     scanf("%d", &t);
180     while ( t-- )
181     {
182         scanf("%d", &n);
183         init();
184         for ( int i = 1; i < n; i++ )
185         {
186             int u, v, w;
187             scanf("%d%d%d", &u, &v, &w);
188             addEdge( u, v, w );
189             addEdge( v, u, w );
190             d[i].u = u, d[i].v = v;
191         }
192         dfs1( 1, -1, 1 );
193         dfs2( 1, 1 );
194         build( 1, 2, n );
195         char op[11];
196         int x, y;
197         while ( 1 )
198         {
199             scanf("%s", op);
200             if ( op[0] == ‘D‘ ) break;
201             scanf("%d%d", &x, &y);
202             if ( op[0] == ‘Q‘ )
203             {
204                 printf("%d\n", tree_query( x, y ));
205             }
206             else
207             {
208                 tree_update( x, y );
209             }
210         }
211     }
212     return 0;
213 }

bzoj 1036 点有权值:

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5
  6 const int INF = -9999999;
  7 const int N = 30001;
  8 int c[N];
  9 int head[N];
 10 int sz[N];
 11 int depth[N];
 12 int num[N];
 13 int top[N];
 14 int dfn[N];
 15 int hc[N];
 16 int fa[N];
 17 int n, e, dfs_clock;
 18
 19 void init()
 20 {
 21     e = dfs_clock = 0;
 22     memset( head, -1, sizeof(head) );
 23 }
 24
 25 struct Edge
 26 {
 27     int v, next;
 28 } edge[N << 1];
 29
 30 void addEdge( int u, int v )
 31 {
 32     edge[e].v = v;
 33     edge[e].next = head[u];
 34     head[u] = e++;
 35 }
 36
 37 void dfs1( int u, int pre, int dep )
 38 {
 39     sz[u] = 1;
 40     fa[u] = pre;
 41     depth[u] = dep;
 42     hc[u] = -1;
 43     for ( int i = head[u]; i != -1; i = edge[i].next )
 44     {
 45         int v = edge[i].v;
 46         if ( v == pre ) continue;
 47         dfs1( v, u, dep + 1 );
 48         sz[u] += sz[v];
 49         if ( hc[u] == -1 || sz[v] > sz[hc[u]] )
 50         {
 51             hc[u] = v;
 52         }
 53     }
 54 }
 55
 56 void dfs2( int u, int tp )
 57 {
 58     top[u] = tp;
 59     dfn[u] = ++dfs_clock;
 60     num[dfn[u]] = c[u];
 61     if ( hc[u] != -1 )
 62     {
 63         dfs2( hc[u], tp );
 64     }
 65     for ( int i = head[u]; i != -1; i = edge[i].next )
 66     {
 67         int v = edge[i].v;
 68         if ( v == fa[u] || v == hc[u] ) continue;
 69         dfs2( v, v );
 70     }
 71 }
 72
 73 struct Node
 74 {
 75     int l, r;
 76     int maxn, sum;
 77 } node[N << 2];
 78
 79 void pushup( int i )
 80 {
 81     node[i].maxn = max( node[i << 1].maxn, node[i << 1 | 1].maxn );
 82     node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;
 83 }
 84
 85 void build( int i, int l, int r )
 86 {
 87     node[i].l = l, node[i].r = r;
 88     if ( l == r )
 89     {
 90         node[i].maxn = node[i].sum = num[l];
 91         return ;
 92     }
 93     int mid = ( l + r ) >> 1;
 94     build( i << 1, l, mid );
 95     build( i << 1 | 1, mid + 1, r );
 96     pushup(i);
 97 }
 98
 99 void update( int i, int pos, int val )
100 {
101     if ( node[i].l == pos && node[i].r == pos )
102     {
103         node[i].maxn = node[i].sum = val;
104         return ;
105     }
106     int mid = ( node[i].l + node[i].r ) >> 1;
107     if ( pos <= mid )
108     {
109         update( i << 1, pos, val );
110     }
111     else
112     {
113         update( i << 1 | 1, pos, val );
114     }
115     pushup(i);
116 }
117
118 int query_max( int i, int l, int r )
119 {
120     if ( node[i].l == l && node[i].r == r )
121     {
122         return node[i].maxn;
123     }
124     int mid = ( node[i].l + node[i].r ) >> 1;
125     if ( r <= mid )
126     {
127         return query_max( i << 1, l, r );
128     }
129     else if ( l > mid )
130     {
131         return query_max( i << 1 | 1, l, r );
132     }
133     else
134     {
135         return max( query_max( i << 1, l, mid ), query_max( i << 1 | 1, mid + 1, r ) );
136     }
137 }
138
139 int query_sum( int i, int l, int r )
140 {
141     if ( node[i].l == l && node[i].r == r )
142     {
143         return node[i].sum;
144     }
145     int mid = ( node[i].l + node[i].r ) >> 1;
146     if ( r <= mid )
147     {
148         return query_sum( i << 1, l, r );
149     }
150     else if ( l > mid )
151     {
152         return query_sum( i << 1 | 1, l, r );
153     }
154     else
155     {
156         return query_sum( i << 1, l, mid ) + query_sum( i << 1 | 1, mid + 1, r );
157     }
158 }
159
160 int tree_query_max( int x, int y )
161 {
162     int ans = INF;
163     while ( top[x] != top[y] )
164     {
165         if ( depth[top[x]] < depth[top[y]] )
166         {
167             swap( x, y );
168         }
169         ans = max( ans, query_max( 1, dfn[top[x]], dfn[x] ) );
170         x = fa[top[x]];
171     }
172     if ( depth[x] > depth[y] ) swap( x, y );
173     ans = max( ans, query_max( 1, dfn[x], dfn[y] ) );
174     return ans;
175 }
176
177 int tree_query_sum( int x, int y )
178 {
179     int ans = 0;
180     while ( top[x] != top[y] )
181     {
182         if ( depth[top[x]] < depth[top[y]] )
183         {
184             swap( x, y );
185         }
186         ans += query_sum( 1, dfn[top[x]], dfn[x] );
187         x = fa[top[x]];
188     }
189     if ( depth[x] > depth[y] ) swap( x, y );
190     ans += query_sum( 1, dfn[x], dfn[y] );
191     return ans;
192 }
193
194 int main ()
195 {
196     while ( scanf("%d", &n) != EOF )
197     {
198         init();
199         for ( int i = 1; i < n; i++ )
200         {
201             int u, v;
202             scanf("%d%d", &u, &v);
203             addEdge( u, v );
204             addEdge( v, u );
205         }
206         for ( int i = 1; i <= n; i++ )
207         {
208             scanf("%d", c + i);
209         }
210         dfs1( 1, -1, 1 );
211         dfs2( 1, 1 );
212         build( 1, 1, n );
213         char op[11];
214         int m, x, y;
215         scanf("%d", &m);
216         while ( m-- )
217         {
218             scanf("%s%d%d", op, &x, &y);
219             if ( op[1] == ‘M‘ )
220             {
221                 printf("%d\n", tree_query_max( x, y ));
222             }
223             else if ( op[1] == ‘S‘ )
224             {
225                 printf("%d\n", tree_query_sum( x, y ));
226             }
227             else
228             {
229                 update( 1, dfn[x], y );
230             }
231         }
232     }
233     return 0;
234 }
时间: 2024-10-11 07:20:37

spoj 375 AND bzoj 1036 树链剖分的相关文章

bzoj 1036 树链剖分+线段树 裸题

HYSBZ - 1036 题意:中文题 思路:树链剖分裸题,线段树写得比较搓,(在线段树上修改节点u的时候应该修改u映射到线段树后的节点序号,这里wa了半年,真的是半年) AC代码: #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector

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 3083 树链剖分

首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区间,后者询问区间的补集. /************************************************************** Problem: 3083 User: BLADEVIL Language: C++ Result: Accepted Time:6412 ms

HYSBZ 1036 树链剖分(单点更新区间求和求最大值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1036 Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身 Input 输入

spoj Query on a tree(树链剖分模板题)

375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of

BZOJ 2243 树链剖分

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 题意:中文题目 思路:树链剖分.首先考虑求区间颜色段数的问题, 我们可以用线段树维护:区间左右端点(st,ed),区间颜色段数(val),懒惰标记(lazy:是否整个区间被染成同一种颜色),区间左右端点的颜色(lcolor,rcolor),然后在查询的时候如果当前区间的左子树的右端点的颜色等于右子树的左端点的颜色,那么查询答案要减一.由于树链剖分在查询时是有可能两端的分链一起向上爬

SPOJ Query on a tree 树链剖分 水题

You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to tior QUERY a b : ask fo

BZOJ 4326 树链剖分+二分+差分+记忆化

去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <ctime> 6 #include <cstdlib> 7 using namespace std; 8 const int Maxn=300100

bzoj 4196 树链剖分 模板

[Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2135  Solved: 1232[Submit][Status][Discuss] Description Linux用户和OSX用户一定对软件包管理器不会陌生.通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置.Debian/Ubu