SPOJ QTREE4 Query on a tree IV (邊分治 + 堆)
阿新 • • 發佈:2019-02-19
題意:
給定一棵樹,節點有黑白兩種顏色,有正負的邊權。
有兩種操作:
一種是修改反轉某個節點的顏色;
另一種是詢問樹上最遠的兩個白色節點的距離。
思路:
樹剖+堆維護的程式碼還是沒敢去碼。。以後再補了。。
這裡用邊分治+堆來維護。
邊分治的優點比起點分支來說,優點就是每次分治之後,只有兩個分支,處理起來比較簡單,程式碼比較好寫。缺點就是需要新增虛點,常數比較大。
邊分治就是先新增虛點,使得每個節點的度數小於等於3,新增虛點的方法很容易看懂。
邊分治就是選在當前分治結構裡面選一條邊,使得邊的兩端最大聯通塊儘可能的小。
對於一個分治結構,假設找到的分治的邊為x-y,對於這個分治結構中的路徑只有兩種,不經過邊x-y的和經過邊x-y的,前者由子分治結構來考慮,現在只考慮後者。可以對邊x-y兩端分別維護兩個大頂堆,堆裡面放的是白色節點距離x的距離或者白色節點距離y的距離。所以經過x-y的最大路徑就是兩個堆的最大值加上x-y的邊權。但是有修改操作,我們可以在堆裡面再維護一個值,就是節點號x,如果堆頂的節點是黑色的話,說明這個節點已經不能用了,要pop掉。所以對每個節點要維護它所在的每一個分治結構,並且記錄它是在分支結構的哪一邊,更新的時候要沿著分治結構自底向上更新,最後詢問的時候就是O(1),更新是O(lognlogn)。
#include<iostream> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<set> #include<algorithm> using namespace std; #define LL long long #define eps 1e-8 #define MP make_pair #define N 200020 #define M 400020 #define NLGN 400002 #pragma comment(linker, "/STACK:1024000000,1024000000") #define ls (i << 1) #define rs (ls | 1) #define md ((ll + rr) >> 1) #define lson ll, md, ls #define rson md + 1, rr, rs #define mod 258280327 #define inf 0x3f3f3f3f #define pii pair<int, int> #define ULL unsigned long long int readint() { char c; while((c = getchar()) && !(c >= '0' && c <= '9') && c != '-'); int ret = c - '0', sgn = 0; if(c == '-') sgn = 1, ret = 0; while((c = getchar()) && c >= '0' && c <= '9') ret = ret * 10 + c - '0'; if(sgn) ret = -ret; return ret; } char buf[8000000],*pt = buf,*o = buf; int getint(){ int f = 1,x = 0; while((*pt != '-') && (*pt < '0' || *pt > '9')) pt ++; if(*pt == '-') f = -1,pt ++; else x = *pt++ - 48; while(*pt >= '0' && *pt <= '9') x = x * 10 + *pt ++ - 48; return x * f; } char getch(){ char ch; while(*pt < 'A' || *pt > 'Z') pt ++; ch=*pt;pt++; return ch; } struct node { int x, v; node() {} node(int x, int v):x(x), v(v) {}; bool operator < (const node &b) const { return v < b.v; } }; struct P { int p, t, d; P() {} P(int p, int t, int d): p(p), t(t), d(d) {} }; vector<P> vt[N]; vector<node> g[N]; int n, fst[N], nxt[M], vv[M], cost[M], e; bool del[M]; int tot, cnt, sz[N]; void init() { memset(fst, -1, sizeof fst); e = 0; } void add(int u, int v, int c) { del[e] = 0, vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++; del[e] = 0, vv[e] = u, nxt[e] = fst[v], cost[e] = c, fst[v] = e++; } vector<node> t; int mx[NLGN], cc[NLGN], LC[NLGN], RC[NLGN]; priority_queue<node> q[NLGN][2]; priority_queue<node> Q; int ans; bool col[N]; void dfs(int u, int p) { int fa = 0; for(int i = 0; i < g[u].size(); ++i) { int v = g[u][i].x; if(v == p) continue; if(fa == 0) { add(u, v, g[u][i].v); fa = u; } else { int k = ++tot; add(fa, k, 0); add(k, v, g[u][i].v); fa = k; } dfs(v, u); } } void dfs1(int u, int p) { sz[u] = 1; for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; if(v == p || del[i]) continue; dfs1(v, u); sz[u] += sz[v]; } } pii dfs2(int u, int p, int tt) { pii ret(inf, -1); for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; if(v == p || del[i]) continue; int x = max(sz[v], tt - sz[v]); if(x < ret.first) ret = MP(x, i); pii t = dfs2(v, u, tt); if(t.first < ret.first) ret = t; } return ret; } void dfs3(int u, int p, int k, int t, int d) { if(u >= 1 && u <= n) { vt[u].push_back(P(k, t, d)); q[k][t].push(node(u, d)); } for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i], c = cost[i]; if(v == p || del[i]) continue; dfs3(v, u, k, t, d + c); } } void update(int p) { while(!q[p][0].empty()) { if(col[q[p][0].top().x]) { q[p][0].pop(); continue; } break; } while(!q[p][1].empty()) { if(col[q[p][1].top().x]) { q[p][1].pop(); continue; } break; } if(q[p][0].empty() || q[p][1].empty()) mx[p] = 0; else mx[p] = q[p][0].top().v + q[p][1].top().v + cc[p]; if(LC[p]) mx[p] = max(mx[p], mx[LC[p]]); if(LC[p]) mx[p] = max(mx[p], mx[RC[p]]); } int calc(int u) { dfs1(u, -1); int id = dfs2(u, -1, sz[u]).second; if(id == -1) return 0; int x = vv[id], y = vv[id^1]; del[id] = del[id^1] = 1; int t = ++cnt; dfs3(x, -1, t, 0, 0); dfs3(y, -1, t, 1, 0); LC[t] = calc(x); RC[t] = calc(y); cc[t] = cost[id]; ans = max(ans, mx[t]); update(t); return t; } int main() { // freopen("tt.txt", "r", stdin); fread(buf,1,8000000,stdin); while(1) { n = getint(); init(); for(int i = 1; i < n; ++i) { int u, v, c; u = getint(); v = getint(); c = getint(); g[u].push_back(node(v, c)); g[v].push_back(node(u, c)); } tot = n; dfs(1, -1); ans = 0; calc(1); int qq; qq = getint(); int node_cnt = n; while(qq--) { char s[10]; int u; s[0] = getch(); if(s[0] == 'A') { if(node_cnt == 0) { puts("They have disappeared."); } else printf("%d\n", max(0, mx[1])); continue; } u = getint(); if(col[u]) { ++node_cnt; col[u] = 0; for(int i = vt[u].size() - 1; i >= 0; --i) { int p = vt[u][i].p; int t = vt[u][i].t; int d = vt[u][i].d; q[p][t].push(node(u, d)); update(p); } } else { --node_cnt; col[u] = 1; for(int i = vt[u].size() - 1; i >= 0; --i) { int p = vt[u][i].p; update(p); } } } } return 0; }