题目链接:http://poj.org/problem?id=3237
题意:
给出N个节点的树,每条边有权值。有3种操作:
CHANGE
i v 改变第i条边的权值,变成v
NEGATE
a b a到b的路径上的每条边的权值取相反数
QUERY
a b 找出a到b路径上权值最大的边输出
思路:
权值在边上的树链剖分+线段树单点更新+线段树成段更新+线段树成段询问。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <vector> 5 #include <algorithm> 6 using namespace std; 7 #define lson l, m, rt<<1 8 #define rson m+1, r, rt<<1|1 9 #define maxn 10010 10 struct Node 11 { 12 int to, val; 13 Node(int t, int v) 14 { 15 to = t; val = v; 16 } 17 Node(){} 18 }; 19 struct Edge 20 { 21 int from, to, val; 22 }e[maxn]; 23 vector <Node> mp[maxn]; 24 int N; 25 int siz[maxn]; //表示以v为根的子树的节点数 26 int dep[maxn]; //表示v的深度(根深度为1) 27 int top[maxn]; //表示v所在的重链的顶端节点 28 int fa[maxn]; //表示v的父亲 29 int son[maxn]; //表示与v在同一重链上的v的儿子节点(姑且称为重儿子) 30 int w[maxn]; //表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置 31 int pos; 32 int mmax[maxn<<2], mmin[maxn<<2],col[maxn<<2]; 33 void PushUp(int rt) 34 { 35 mmax[rt] = max(mmax[rt<<1], mmax[rt<<1|1]); 36 mmin[rt] = min(mmin[rt<<1], mmin[rt<<1|1]); 37 } 38 void PushDown(int rt) 39 { 40 if(col[rt]) 41 { 42 col[rt<<1] ^= 1; col[rt<<1|1] ^= 1; 43 int tempmax, tempmin; 44 tempmax = mmax[rt<<1]; tempmin = mmin[rt<<1]; 45 mmax[rt<<1] = -tempmin; mmin[rt<<1] = -tempmax; 46 tempmax = mmax[rt<<1|1]; tempmin = mmin[rt<<1|1]; 47 mmax[rt<<1|1] = -tempmin; mmin[rt<<1|1] = -tempmax; 48 col[rt] = 0; 49 } 50 } 51 void build(int l, int r, int rt) 52 { 53 col[rt] = 0; 54 mmax[rt] = -0x3f3f3f3f; 55 mmin[rt] = 0x3f3f3f3f; 56 57 if(l == r) return; 58 int m = (l+r)>>1; 59 build(lson); 60 build(rson); 61 PushUp(rt); 62 } 63 void update(int p, int val, int l, int r, int rt) 64 { 65 if(l == r) 66 { 67 col[rt] = 0; 68 mmax[rt] = val; mmin[rt] = val; 69 return; 70 } 71 PushDown(rt); 72 int m = (l+r)>>1; 73 if(p <= m) update(p, val, lson); 74 else update(p, val, rson); 75 PushUp(rt); 76 } 77 void update2(int L, int R, int l, int r, int rt) 78 { 79 if(L <= l && R >= r) 80 { 81 col[rt] ^= 1; 82 int tempmax = mmax[rt], tempmin = mmin[rt]; 83 mmax[rt] = -tempmin; mmin[rt] = -tempmax; 84 return; 85 } 86 PushDown(rt); 87 int m = (l+r)>>1; 88 if(L <= m) update2(L, R, lson); 89 if(R > m) update2(L, R, rson); 90 PushUp(rt); 91 } 92 int query(int L, int R, int l, int r, int rt) 93 { 94 if(L <= l && R >= r) 95 { 96 return mmax[rt]; 97 } 98 PushDown(rt); 99 int ret = -0x3f3f3f3f; 100 int m = (l+r)>>1; 101 if(L <= m) ret = max(ret, query(L, R, lson)); 102 if(R > m) ret = max(ret, query(L, R, rson)); 103 return ret; 104 } 105 int dfs1(int u, int pre, int deep) 106 { 107 siz[u] = 1; dep[u] = deep; fa[u] = pre; 108 int mmax = 0; 109 for(int i = 0; i < mp[u].size(); i++) 110 { 111 if(mp[u][i].to != pre) 112 { 113 int temp = dfs1(mp[u][i].to, u, deep+1); 114 siz[u] += temp; 115 if(son[u] == -1 || temp >= mmax) son[u] = mp[u][i].to; 116 } 117 } 118 return siz[u]; 119 } 120 void dfs2(int u, int val) 121 { 122 top[u] = val; 123 if(son[u] != -1) //如果不是叶子节点,线段树中,v的重边应当在v的父边的后面 124 { 125 w[u] = pos++; 126 dfs2(son[u], val); 127 } 128 else if(son[u] == -1) 129 { 130 w[u] = pos++; 131 return; 132 } 133 for(int i = 0; i < mp[u].size(); i++) 134 { 135 if(mp[u][i].to != son[u] && mp[u][i].to != fa[u]) dfs2(mp[u][i].to, mp[u][i].to);//对于v的各个轻儿子u,top[u] = u 136 } 137 } 138 int find(int u, int v) 139 { 140 int f1 = top[u], f2 = top[v]; 141 int temp = -0x3f3f3f3f; 142 while(f1 != f2) 143 { 144 if(dep[f1] < dep[f2]) //设dep[f1] >= dep[f2] 145 { 146 swap(f1, f2); 147 swap(u, v); 148 } 149 temp = max(temp, query(w[f1],w[u], 1, pos-1, 1)); 150 u = fa[f1]; f1 = top[u]; 151 } 152 if(u == v) return temp; 153 if(dep[u] > dep[v]) swap(u, v); 154 return max(temp, query(w[son[u]], w[v], 1, pos-1, 1)); 155 } 156 void Negate(int u, int v) 157 { 158 int f1 = top[u], f2 = top[v]; 159 while(f1 != f2) 160 { 161 if(dep[f1] < dep[f2]) 162 { 163 swap(f1, f2); 164 swap(u, v); 165 } 166 update2(w[f1], w[u], 1, pos-1, 1); 167 u = fa[f1]; f1 = top[u]; 168 } 169 if(u == v) return; 170 if(dep[u] > dep[v]) swap(u, v); 171 update2(w[son[u]], w[v], 1, pos-1, 1); 172 } 173 int main() 174 { 175 // freopen("in.txt", "r", stdin); 176 //freopen("out.txt", "w", stdout); 177 int T; scanf("%d", &T); 178 while(T--) 179 { 180 scanf("%d", &N); 181 pos = 0; memset(son, -1, sizeof(son)); 182 for(int i = 1; i <= N; i++) mp[i].clear(); 183 for(int i = 1; i <= N-1; i++) 184 { 185 scanf("%d%d%d", &e[i].from, &e[i].to, &e[i].val); 186 mp[e[i].from].push_back(Node(e[i].to, e[i].val)); 187 mp[e[i].to].push_back(Node(e[i].from, e[i].val)); 188 } 189 dfs1(1, -1, 1); 190 dfs2(1, 1); 191 build(1, pos-1, 1); 192 for(int i = 1; i <= N-1; i++) 193 { 194 if(dep[e[i].from] > dep[e[i].to]) 195 { 196 swap(e[i].from, e[i].to); 197 } 198 update(w[e[i].to], e[i].val, 1, pos-1, 1); 199 } 200 char op[15]; 201 while(scanf("%s", op)) 202 { 203 if(op[0] == 'D') break; 204 int a, b; scanf("%d%d", &a, &b); 205 if(op[0] == 'Q') printf("%d ", find(a, b)); 206 else if(op[0] == 'C') update(w[e[a].to], b, 1, pos-1, 1); 207 else if(op[0] == 'N') Negate(a, b); 208 209 } 210 } 211 212 return 0; 213 }