[SPOJ]Query on a tree(树链剖分,线段树)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SPOJ]Query on a tree(树链剖分,线段树)相关的知识,希望对你有一定的参考价值。

题目链接:http://www.spoj.com/problems/QTREE/en/

照着集训队论文敲的…万幸树剖部分没写错…

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <fstream>
  8 #include <cassert>
  9 #include <cstdio>
 10 #include <bitset>
 11 #include <vector>
 12 #include <deque>
 13 #include <queue>
 14 #include <stack>
 15 #include <ctime>
 16 #include <set>
 17 #include <map>
 18 #include <cmath>
 19 
 20 using namespace std;
 21 #define fr first
 22 #define sc second
 23 #define cl clear
 24 #define BUG puts("here!!!")
 25 #define W(a) while(a--)
 26 #define pb(a) push_back(a)
 27 #define Rint(a) scanf("%d", &a)
 28 #define Rll(a) scanf("%I64d", &a)
 29 #define Rs(a) scanf("%s", a)
 30 #define Cin(a) cin >> a
 31 #define FRead() freopen("in", "r", stdin)
 32 #define FWrite() freopen("out", "w", stdout)
 33 #define Rep(i, len) for(int i = 0; i < (len); i++)
 34 #define For(i, a, len) for(int i = (a); i < (len); i++)
 35 #define Cls(a) memset((a), 0, sizeof(a))
 36 #define Clr(a, p) memset((a), (p), sizeof(a))
 37 #define Full(a) memset((a), 0x7f7f7f, sizeof(a))
 38 #define lrt rt << 1
 39 #define rrt rt << 1 | 1
 40 #define pi 3.14159265359
 41 #define RT return
 42 #define lowbit(p) p & (-p)
 43 #define onenum(p) __builtin_popcount(p)
 44 typedef long long LL;
 45 typedef long double LD;
 46 typedef unsigned long long ULL;
 47 typedef pair<int, int> pii;
 48 typedef pair<string, int> psi;
 49 typedef pair<LL, LL> pll;
 50 typedef map<string, int> msi;
 51 typedef vector<int> vi;
 52 typedef vector<LL> vl;
 53 typedef vector<vl> vvl;
 54 typedef vector<bool> vb;
 55 
 56 typedef struct Edge {
 57     int v, w;
 58     Edge() {}
 59     Edge(int vv, int ww) : v(vv), w(ww) {}
 60 }Edge;
 61 const int maxn = 10100;
 62 int n, k;
 63 int depth[maxn];    //点的深度
 64 int siz[maxn];        //以该点为树根,子树的点数
 65 int fa[maxn];            //父亲节点编号
 66 int son[maxn];        //重儿子编号
 67 int top[maxn];        //点所在的重链的顶端节点
 68 int p[maxn];            //点与其父亲节点的连边在线段树中的位置
 69 int pos;
 70 vector<Edge> G[maxn];
 71 char cmd[15];
 72 
 73 int dfs1(int p, int u, int d) {
 74     siz[u] = 1; depth[u] = d; fa[u] = p;
 75     Rep(i, G[u].size()) {
 76         int& v = G[u][i].v;
 77         if(v == p) continue;
 78         siz[u] += dfs1(u, v, d+1);
 79         if(son[u] == -1 || siz[v] > siz[son[u]]) {
 80             son[u] = v;
 81         }
 82     }
 83     return siz[u];
 84 }
 85 
 86 void dfs2(int u, int tp) {
 87     top[u] = tp; p[u] = ++pos;
 88     if(son[u] != -1) dfs2(son[u], top[u]);
 89     Rep(i, G[u].size()) {
 90         int& v = G[u][i].v;
 91         if(v != son[u] && v != fa[u]) {
 92             dfs2(v, v);
 93         }
 94     }
 95 }
 96 
 97 #define lson l, m, rt << 1
 98 #define rson m + 1, r, rt << 1 | 1
 99 int sum[maxn<<2];
100 
101 void pushUP(int rt) {
102     sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
103 }
104 
105 void build(int l, int r, int rt) {
106     sum[rt] = 0;
107     if(l == r) return;
108     int m = (l + r) >> 1;
109     build(lson);
110     build(rson);
111     pushUP(rt);
112 }
113 
114 void update(int p, int x, int l, int r, int rt) {
115     if(l == r) {
116         sum[rt] = x;
117         return;
118     }
119     int m = (l + r) >> 1;
120     if(p <= m) update(p, x, lson);
121     else update(p, x, rson);
122     pushUP(rt);
123 }
124 
125 int query(int L, int R, int l, int r, int rt) {
126     if(L <= l && r <= R) return sum[rt];
127     int m = (l + r) >> 1;
128     int ret = 0;
129     if(L <= m) ret = max(ret, query(L, R, lson));
130     if(R > m) ret = max(ret, query(L, R, rson));
131     return ret;
132 }
133 
134 int find(int u, int v) {
135     int f1 = top[u], f2 = top[v];
136     int tmp = 0;
137     while(f1 != f2) {
138         if(depth[f1] < depth[f2]) {
139             swap(f1, f2);
140             swap(u, v);
141         }
142         tmp = max(tmp, query(p[f1], p[u], 1, pos, 1));
143         u = fa[f1];
144         f1 = top[u];
145     }
146     if(u == v) return tmp;
147     if(depth[u] > depth[v]) swap(u, v);
148     return max(tmp, query(p[son[u]], p[v], 1, pos, 1));
149 }
150 
151 int e[maxn][3];
152 
153 signed main() {
154     // FRead();
155     int T, u, v, w;
156     Rint(T);
157     W(T) {
158         Rint(n);
159         For(i, 1, n+5) G[i].clear();
160         Cls(siz); Cls(depth); Clr(son, -1); Clr(fa, -1); pos = 0; Cls(sum);
161         Rep(i, n-1) {
162             Rint(u); Rint(v); Rint(w);
163             G[u].push_back(Edge(v, w));
164             G[v].push_back(Edge(u, w));
165             e[i+1][0] = u; e[i+1][1] = v; e[i+1][2] = w;
166         }
167         dfs1(-1, 1, 0);
168         dfs2(1, 1);
169         build(1, pos, 1);
170         For(i, 1, n) {
171             u = e[i][0]; v = e[i][1]; w = e[i][2];
172             if(depth[u] > depth[v]) {
173                 swap(e[i][0], e[i][1]);
174                 swap(u, v);
175             }
176             update(p[v], w, 1, pos, 1);
177         }
178         while(~Rs(cmd) && cmd[0] != D) {
179             Rint(u); Rint(v);
180             if(cmd[0] == Q) {
181                 printf("%d\n", find(u, v));
182             }
183             if(cmd[0] == C) {
184                 update(p[e[u][1]], v, 1, pos, 1);
185             }
186         }
187     }
188     RT 0;
189 }

 

以上是关于[SPOJ]Query on a tree(树链剖分,线段树)的主要内容,如果未能解决你的问题,请参考以下文章

SPOJ QTREE Query on a tree ——树链剖分 线段树

SPOJ Query on a tree (树链剖分)

[SPOJ]Query on a tree(树链剖分,线段树)

SPOJ QTREE Query on a Tree树链剖分模板题

[SPOJ2666][ZJOI2007]捉迷藏Query on a tree IV(树链剖分)(论文做法)

SPOJ 375 Query on a tree