Tree 【POJ - 3237】【樹鏈剖分+一些特殊的處理】
阿新 • • 發佈:2019-01-06
題目連結
這道題,說來還的確困擾了我一個多小時,當時就在想,我該如何處理那些邊權(我將邊化為點)以及點(預設權值為0)的取相反數後的處理(因為點取相反數之後還是0),會困擾到那些邊的。
然後,我想到了,如果這段區間的返回的值為0,那麼就說明了肯定是點的,我們不妨返回的是(-INF)即可。然後,再pushup()的時候,也做了相似的處理,畢竟,兩點之間確定一條邊,所以,我們線段樹的操作的時候,如果,左兒子或者右兒子為0,我們取另外一頭,絕對是可以的,於是,就這樣子敲了,A了!
最後,附上一組測試陣列,那個“-48”過了,基本問題不大(我就是一直卡在“-48”),過了,就沒其他問題了。
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 40000007 using namespace std; typedef unsigned long long ull; typedef long long ll; const int maxN = 20005; int N, all_point, W[maxN], cnt, head[maxN], deep[maxN], root[maxN], siz[maxN], W_son[maxN], top[maxN], id[maxN], new_W[maxN], num, tree[maxN<<2], minn[maxN<<2], lazy[maxN<<2]; struct Eddge { int nex, to; Eddge(int a=-1, int b=0):nex(a), to(b) {} }edge[maxN<<1]; void addEddge(int u, int v) { edge[cnt] = Eddge(head[u], v); head[u] = cnt++; } inline void dfs1(int u, int fa, int depth) { root[u] = fa; deep[u] = depth; siz[u] = 1; int Minn = -1; for(int i=head[u]; i!=-1; i=edge[i].nex) { int v = edge[i].to; if(v == fa) continue; dfs1(v, u, depth+1); siz[u] += siz[v]; if(siz[v] > Minn) { Minn = siz[v]; W_son[u] = v; } } } inline void dfs2(int u, int topf) { top[u] = topf; id[u] = ++num; new_W[num] = W[u]; if(W_son[u] == 0) return; dfs2(W_son[u], topf); for(int i=head[u]; i!=-1; i=edge[i].nex) { int v = edge[i].to; if(v == root[u] || v == W_son[u]) continue; dfs2(v, v); } } void pushup(int rt) { if(tree[rt<<1] == 0) { tree[rt] = tree[rt<<1|1]; minn[rt] = minn[rt<<1|1]; return; } if(tree[rt<<1|1] == 0) { tree[rt] = tree[rt<<1]; minn[rt] = minn[rt<<1]; return; } tree[rt] = max(tree[rt<<1], tree[rt<<1|1]); minn[rt] = min(minn[rt<<1], minn[rt<<1|1]); } inline void buildTree(int rt, int l, int r) { lazy[rt] = 0; if(l == r) { tree[rt] = minn[rt] = new_W[l]; return; } int mid = (l + r)>>1; buildTree(rt<<1, l, mid); buildTree(rt<<1|1, mid+1, r); pushup(rt); } void pushdown(int rt) { if(lazy[rt]) { lazy[rt<<1] ^= 1; lazy[rt<<1|1] ^= 1; int t1 = tree[rt<<1], t2 = tree[rt<<1|1]; tree[rt<<1] = -minn[rt<<1]; minn[rt<<1] = -t1; tree[rt<<1|1] = -minn[rt<<1|1]; minn[rt<<1|1] = -t2; lazy[rt] = 0; } } void update_1(int rt, int l, int r, int qx, int val) { if(l == r) { tree[rt] = minn[rt] = val; return; } pushdown(rt); int mid = (l + r)>>1; if(qx<=mid) update_1(rt<<1, l, mid, qx, val); else update_1(rt<<1|1, mid+1, r, qx, val); pushup(rt); } void update_2(int rt, int l, int r, int ql, int qr) { if(ql<=l && qr>=r) { lazy[rt] ^= 1; int tmp = tree[rt]; tree[rt] = -minn[rt]; minn[rt] = -tmp; return; } pushdown(rt); int mid = (l + r)>>1; if(ql>mid) update_2(rt<<1|1, mid+1, r, ql, qr); else if(qr<=mid) update_2(rt<<1, l, mid, ql, qr); else { update_2(rt<<1, l, mid, ql, qr); update_2(rt<<1|1, mid+1, r, ql, qr); } pushup(rt); } void change_line(int pos, int val) { update_1(1, 1, all_point, id[pos + N], val); } void Negate_line(int x, int y) { while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x, y); update_2(1, 1, all_point, id[top[x]], id[x]); x = root[top[x]]; } if(deep[x] > deep[y]) swap(x, y); update_2(1, 1, all_point, id[x], id[y]); } int query(int rt, int l, int r, int ql, int qr) { if(ql<=l && qr>=r) return tree[rt] == 0?(-INF):tree[rt]; pushdown(rt); int mid = (l + r)>>1; if(ql > mid) return query(rt<<1|1, mid+1, r, ql, qr); else if(qr <= mid) return query(rt<<1, l, mid, ql, qr); else return max(query(rt<<1, l, mid, ql, qr), query(rt<<1|1, mid+1, r, ql, qr)); } int query_range(int x, int y) { int ans = -INF; while(top[x] != top[y]) { if(deep[top[x]] < deep[top[y]]) swap(x, y); ans = max(ans, query(1, 1, all_point, id[top[x]], id[x])); x = root[top[x]]; } if(deep[x] > deep[y]) swap(x, y); ans = max(ans, query(1, 1, all_point, id[x], id[y])); return ans; } inline void init() { cnt = num = 0; memset(W, 0, sizeof(W)); memset(W_son, 0, sizeof(W_son)); memset(head, -1, sizeof(head)); } char op[10]; int main() { int T; scanf("%d", &T); while(T--) { init(); scanf("%d", &N); all_point = N; for(int i=1; i<N; i++) { int e1, e2, e3; scanf("%d%d%d", &e1, &e2, &e3); W[++all_point] = e3; addEddge(e1, all_point); addEddge(all_point, e1); addEddge(all_point, e2); addEddge(e2, all_point); } dfs1(1, 1, 0); dfs2(1, 1); buildTree(1, 1, all_point); while(scanf("%s", op) && op[0] != 'D') { int e1, e2; scanf("%d%d", &e1, &e2); if(op[0] == 'C') change_line(e1, e2); else if(op[0] == 'N') Negate_line(e1, e2); else printf("%d\n", query_range(e1, e2)); } } return 0; } /* 1 15 7 1 93 6 2 41 6 1 48 14 4 62 12 15 43 7 8 2 2 10 80 7 13 92 13 5 91 13 11 5 15 1 79 2 3 21 9 12 7 15 4 33 Q 13 7 C 6 6 N 13 1 Q 3 15 C 12 11 N 14 11 Q 2 11 N 2 7 Q 6 7 C 11 10 N 3 8 Q 14 8 C 3 4 Q 8 13 C 5 1 N 7 1 Q 1 11 C 11 8 DONE ans: > 92 > 79 > 93 > -48 > 93 > 92 > 92 */