SPOJ - QTREE4 Query on a tree IV 边分治
题意:有一棵数,每个节点有颜色,黑色或者白色,树边有边权,现在有2个操作,1修改某个点的颜色, 2询问2个白点的之前的路径权值最大和是多少。
题解:
边分治思路。
1.重构图。 因为边分治在菊花图的情况下情况不理想,所以需要先把图重新构建一下,是每个点的度数不超过3。
2.找在新图里面 一条边使得 断开这条边的情况下,左右2新树使得较大的那个子树是所有情况下的最小值。
3.开2个优先队列去维护左边新树的白点的最大值, 右边新树的所有白点的最大值, 然后 左边白点+右边白点+中间边就是最大值。
4.对于2个新图都执行 2-3的操作。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define lch(x) tr[x].son[0] 12 #define rch(x) tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 2e5 + 100; 20 struct Node{ 21 int head[N]; int to[N<<1]; 22 int ct[N<<1]; int nt[N<<1]; 23 int tot; 24 void init(){ 25 tot = 0; 26 memset(head, -1, sizeof(head)); 27 return ; 28 }; 29 void add(int u, int v, int val){ 30 to[tot] = v; ct[tot] = val; 31 nt[tot] = head[u]; head[u] = tot++; 32 return ; 33 } 34 }e[2]; 35 int n, u, v, w; 36 void rebuild(int o, int u){ 37 int ff = 0; 38 for(int i = e[0].head[u]; ~i; i = e[0].nt[i]){ 39 v = e[0].to[i], w = e[0].ct[i]; 40 if(v == o) continue; 41 if(!ff){ 42 e[1].add(u, v, w); 43 e[1].add(v, u, w); 44 ff = u; 45 } 46 else { 47 ++n; 48 e[1].add(ff, n, 0); 49 e[1].add(n, ff, 0); 50 e[1].add(v, n, w); 51 e[1].add(n, v, w); 52 ff = n; 53 } 54 rebuild(u, v); 55 } 56 return ; 57 } 58 vector<pll> vc[N]; 59 priority_queue<pll> pq[N<<2][2]; int wedge[N<<2]; 60 int white[N], sz[N]; 61 int cut[N<<1]; 62 int id, maxnum = 0; 63 void get_edge(int o, int u, int num){ 64 sz[u] = 1; 65 int tmp = 0; 66 for(int i = e[1].head[u]; ~i; i = e[1].nt[i]){ 67 int v = e[1].to[i]; 68 if(v == o || cut[i>>1]) continue; 69 get_edge(u, v, num); 70 sz[u] += sz[v]; 71 tmp = max(num-sz[v], sz[v]); 72 if(tmp < maxnum){ 73 id = i; 74 maxnum = tmp; 75 } 76 } 77 return ; 78 } 79 int k = 0, op; 80 void dfs(int o, int u, int w){ 81 sz[u] = 1; 82 if(white[u]){ 83 pq[k][op].push(pll(w, u)); 84 if(op == 0) vc[u].push_back(pll(-k, w)); 85 else vc[u].push_back(pll(k, w)); 86 } 87 for(int i = e[1].head[u]; ~i; i = e[1].nt[i]){ 88 int v = e[1].to[i]; 89 if(v == o || cut[i>>1]) continue; 90 dfs(u, v, w+e[1].ct[i]); 91 sz[u] += sz[v]; 92 } 93 return ; 94 } 95 int ans[N], lch[N], rch[N]; 96 void update(int k){ 97 while(!pq[k][0].empty() && !white[pq[k][0].top().se]) pq[k][0].pop(); 98 while(!pq[k][1].empty() && !white[pq[k][1].top().se]) pq[k][1].pop(); 99 if(pq[k][0].empty() || pq[k][1].empty()) 100 ans[k] = 0; 101 else { 102 int val1 = pq[k][0].top().fi, val2 = pq[k][1].top().fi; 103 int sum = val1 + val2 + wedge[k]; 104 ans[k] = max(sum, 0); 105 } 106 if(lch[k]) ans[k] = max(ans[k], ans[lch[k]]); 107 if(rch[k]) ans[k] = max(ans[k], ans[rch[k]]); 108 return ; 109 } 110 int solve(int u, int num){ 111 if(num == 1) return 0; 112 maxnum = inf; 113 get_edge(0, u, num); 114 int now = ++k, nid = id; 115 cut[nid >> 1] = 1; 116 wedge[k] = e[1].ct[nid]; 117 op = 0; 118 dfs(0, e[1].to[nid], 0); 119 op = 1; 120 dfs(0, e[1].to[nid^1], 0); 121 lch[now] = solve(e[1].to[nid], sz[e[1].to[nid]]); 122 rch[now] = solve(e[1].to[nid^1], sz[e[1].to[nid^1]]); 123 update(now); 124 return now; 125 } 126 void setWhite(int u){ 127 for(int i = vc[u].size()-1; i >= 0; --i){ 128 pll tmp = vc[u][i]; 129 int k = tmp.fi, ct = tmp.se; 130 if(k < 0) pq[-k][0].push(pll(ct, u)); 131 else pq[k][1].push(pll(ct, u)); 132 update(abs(k)); 133 } 134 return ; 135 } 136 void setBlack(int u){ 137 for(int i = vc[u].size()-1; i >= 0; --i) 138 update(abs(vc[u][i].fi)); 139 return ; 140 } 141 int main(){ 142 scanf("%d", &n); 143 int white_num = n, q; 144 char op[10]; 145 e[0].init(); e[1].init(); 146 for(int i = 1; i < n; i++){ 147 scanf("%d%d%d", &u, &v, &w); 148 e[0].add(u, v, w); 149 e[0].add(v, u, w); 150 white[i] = 1; 151 } 152 white[n] = 1; 153 rebuild(0, 1); 154 solve(1, n); 155 scanf("%d", &q); 156 while(q--){ 157 scanf("%s", op); 158 if(op[0] == 'A') { 159 if(white_num == 0) puts("They have disappeared."); 160 else if(white_num == 1) puts("0"); 161 else printf("%d\n", ans[1]); 162 } 163 else { 164 scanf("%d", &u); 165 white[u] ^= 1; 166 if(white[u]) 167 setWhite(u), ++white_num; 168 else 169 setBlack(u), --white_num; 170 } 171 } 172 return 0; 173 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define lch(x) tr[x].son[0] 12 #define rch(x) tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 2e5 + 100; 20 struct Node{ 21 int head[N]; int to[N<<1]; 22 int ct[N<<1]; int nt[N<<1]; 23 int tot; 24 void init(){ 25 tot = 0; 26 memset(head, -1, sizeof(head)); 27 return ; 28 }; 29 void add(int u, int v, int val){ 30 to[tot] = v; ct[tot] = val; 31 nt[tot] = head[u]; head[u] = tot++; 32 return ; 33 } 34 }e[2]; 35 int n, u, v, w; 36 void rebuild(int o, int u){ 37 int ff = 0; 38 for(int i = e[0].head[u]; ~i; i = e[0].nt[i]){ 39 v = e[0].to[i], w = e[0].ct[i]; 40 if(v == o) continue; 41 if(!ff){ 42 e[1].add(u, v, w); 43 e[1].add(v, u, w); 44 ff = u; 45 } 46 else { 47 ++n; 48 e[1].add(ff, n, 0); 49 e[1].add(n, ff, 0); 50 e[1].add(v, n, w); 51 e[1].add(n, v, w); 52 ff = n; 53 } 54 rebuild(u, v); 55 } 56 return ; 57 } 58 vector<pll> vc[N]; 59 priority_queue<pll> pq[N<<2][2]; int wedge[N<<2]; 60 int white[N], sz[N]; 61 int cut[N<<1]; 62 int id, maxnum = 0; 63 void get_edge(int o, int u, int num){ 64 sz[u] = 1; 65 int tmp = 0; 66 for(int i = e[1].head[u]; ~i; i = e[1].nt[i]){ 67 int v = e[1].to[i]; 68 if(v == o || cut[i>>1]) continue; 69 get_edge(u, v, num); 70 sz[u] += sz[v]; 71 tmp = max(num-sz[v], sz[v]); 72 if(tmp < maxnum){ 73 id = i; 74 maxnum = tmp; 75 } 76 } 77 return ; 78 } 79 int k = 0, op; 80 void dfs(int o, int u, int w){ 81 sz[u] = 1; 82 if(white[u]){ 83 pq[k][op].push(pll(w, u)); 84 if(op == 0) vc[u].push_back(pll(-k, w)); 85 else vc[u].push_back(pll(k, w)); 86 } 87 for(int i = e[1].head[u]; ~i; i = e[1].nt[i]){ 88 int v = e[1].to[i]; 89 if(v == o || cut[i>>1]) continue; 90 dfs(u, v, w+e[1].ct[i]); 91 sz[u] += sz[v]; 92 } 93 return ; 94 } 95 int ans[N], lch[N], rch[N]; 96 void update(int k){ 97 while(!pq[k][0].empty() && !white[pq[k][0].top().se]) pq[k][0].pop(); 98 while(!pq[k][1].empty() && !white[pq[k][1].top().se]) pq[k][1].pop(); 99 if(pq[k][0].empty() || pq[k][1].empty()) 100 ans[k] = 0; 101 else { 102 int val1 = pq[k][0].top().fi, val2 = pq[k][1].top().fi; 103 int sum = val1 + val2 + wedge[k]; 104 ans[k] = max(sum, 0); 105 } 106 if(lch[k]) ans[k] = max(ans[k], ans[lch[k]]); 107 if(rch[k]) ans[k] = max(ans[k], ans[rch[k]]); 108 return ; 109 } 110 int solve(int u, int num){ 111 if(num == 1) return 0; 112 maxnum = inf; 113 get_edge(0, u, num); 114 int now = ++k, nid = id; 115 cut[nid >> 1] = 1; 116 wedge[k] = e[1].ct[nid]; 117 op = 0; 118 dfs(0, e[1].to[nid], 0); 119 op = 1; 120 dfs(0, e[1].to[nid^1], 0); 121 lch[now] = solve(e[1].to[nid], sz[e[1].to[nid]]); 122 rch[now] = solve(e[1].to[nid^1], sz[e[1].to[nid^1]]); 123 update(now); 124 return now; 125 } 126 void setWhite(int u){ 127 for(int i = vc[u].size()-1; i >= 0; --i){ 128 pll tmp = vc[u][i]; 129 int k = tmp.fi, ct = tmp.se; 130 if(k < 0) pq[-k][0].push(pll(ct, u)); 131 else pq[k][1].push(pll(ct, u)); 132 update(abs(k)); 133 } 134 return ; 135 } 136 void setBlack(int u){ 137 for(int i = vc[u].size()-1; i >= 0; --i) 138 update(abs(vc[u][i].fi)); 139 return ; 140 } 141 int main(){ 142 scanf("%d", &n); 143 int white_num = n, q; 144 char op[10]; 145 e[0].init(); e[1].init(); 146 for(int i = 1; i < n; i++){ 147 scanf("%d%d%d", &u, &v, &w); 148 e[0].add(u, v, w); 149 e[0].add(v, u, w); 150 white[i] = 1; 151 } 152 white[n] = 1; 153 rebuild(0, 1); 154 solve(1, n); 155 scanf("%d", &q); 156 while(q--){ 157 scanf("%s", op); 158 if(op[0] == 'A') { 159 if(white_num == 0) puts("They have disappeared."); 160 else if(white_num == 1) puts("0"); 161 else printf("%d\n", ans[1]); 162 } 163 else { 164 scanf("%d", &u); 165 white[u] ^= 1; 166 if(white[u]) 167 setWhite(u), ++white_num; 168 else 169 setBlack(u), --white_num; 170 } 171 } 172 return 0; 173 }