SPOJ - QTREE5 Query on a tree V 边分治
题意:给你一棵树, 然后树上的点都有颜色,且原来为黑,现在有2个操作,1 改变某个点的颜色, 2 询问树上的白点到u点的最短距离是多少。
题解:
这里用的还是边分治的方法。
把所有东西都抠出来, 然后每次询问的时候都访问每幅分割图的另外一侧。
代码:
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], to[N<<1], nt[N<<1], ct[N<<1]; 22 int tot; 23 void init(){ 24 memset(head, -1, sizeof(head)); 25 tot = 0; 26 } 27 void add(int u, int v, int cost){ 28 ct[tot] = cost; 29 to[tot] = v; 30 nt[tot] = head[u]; 31 head[u] = tot++; 32 } 33 }e[2]; 34 int n, m, white[N], cut[N<<1]; 35 void rebuild(int o, int u){ 36 int ff = 0; 37 for(int i = e[0].head[u]; ~i; i = e[0].nt[i]){ 38 int v = e[0].to[i]; 39 if(o == v) continue; 40 if(!ff){ 41 e[1].add(u, v, 1); 42 e[1].add(v, u, 1); 43 ff = u; 44 } 45 else { 46 ++n; 47 e[1].add(ff, n, 0); e[1].add(n, ff, 0); 48 e[1].add(n, v, 1); e[1].add(v, n, 1); 49 ff = n; 50 } 51 rebuild(u, v); 52 } 53 } 54 int sz[N], minval, id; 55 void get_edge(int o, int u, int num){ 56 sz[u] = 1; 57 for(int i = e[1].head[u]; ~i; i = e[1].nt[i]){ 58 int v = e[1].to[i]; 59 if(v == o || cut[i>>1]) continue; 60 get_edge(u, v, num); 61 sz[u] += sz[v]; 62 int tmp = max(sz[v], num - sz[v]); 63 if(tmp < minval){ 64 minval = tmp; 65 id = i; 66 } 67 } 68 } 69 int k = 0, op; 70 vector<pll> vc[N]; 71 priority_queue<pll, vector<pll>, greater<pll> > pq[N<<2][2]; 72 int wedge[N<<2]; 73 int mm; 74 void dfs2(int o, int u, int w){ 75 vc[u].pb(pll(k*op, w)); 76 sz[u] = 1; 77 for(int i = e[1].head[u]; ~i; i = e[1].nt[i]){ 78 int v = e[1].to[i]; 79 if(v == o || cut[i>>1]) continue; 80 dfs2(u, v, w + e[1].ct[i]); 81 sz[u] += sz[v]; 82 } 83 } 84 void solve(int u, int num){ 85 if(num <= 1) return ; 86 minval = inf; 87 get_edge(0, u, num); 88 int nid = id; 89 cut[nid>>1] = 1; 90 ++k; 91 op = 1; 92 dfs2(0, e[1].to[nid], 0); 93 op = -1; 94 dfs2(0, e[1].to[nid^1], 0); 95 wedge[k] = e[1].ct[nid]; 96 solve(e[1].to[nid], sz[e[1].to[nid]]); 97 solve(e[1].to[nid^1], sz[e[1].to[nid^1]]); 98 } 99 void Update(int k){ 100 while(!pq[k][0].empty() && !white[pq[k][0].top().se]) pq[k][0].pop(); 101 while(!pq[k][1].empty() && !white[pq[k][1].top().se]) pq[k][1].pop(); 102 } 103 void setwhite(int u){ 104 for(int i = 0; i < vc[u].size(); i++){ 105 int k = vc[u][i].fi, w = vc[u][i].se; 106 if(k < 0) pq[-k][0].push(pll(w,u)); 107 else pq[k][1].push(pll(w,u)); 108 Update(abs(k)); 109 } 110 } 111 void setblack(int u){ 112 for(int i = 0; i < vc[u].size(); i++){ 113 int k = vc[u][i].fi; 114 Update(abs(k)); 115 } 116 } 117 int Find(int u){ 118 int ret = inf; 119 for(int i = 0; i < vc[u].size(); i++){ 120 int k = vc[u][i].fi, w = vc[u][i].se; 121 if(k < 0 && !pq[-k][1].empty()) 122 ret = min(ret, w+wedge[-k]+pq[-k][1].top().fi); 123 if(k > 0 && !pq[k][0].empty()) 124 ret = min(ret, w+wedge[k]+pq[k][0].top().fi); 125 } 126 return ret; 127 } 128 int main(){ 129 e[0].init(); e[1].init(); 130 scanf("%d", &n); 131 int u, v; 132 for(int i = 1; i < n; i++){ 133 scanf("%d%d", &u, &v); 134 e[0].add(u, v, 1); e[0].add(v, u, 1); 135 } 136 memset(white, 0, sizeof(white)); 137 rebuild(0, 1); 138 solve(1, n); 139 int num = 0, op; 140 scanf("%d", &m); 141 while(m--){ 142 scanf("%d%d", &op, &v); 143 if(op == 0){ 144 white[v] ^= 1; 145 if(white[v]){ 146 setwhite(v); 147 num++; 148 } 149 else { 150 setblack(v); 151 num--; 152 } 153 } 154 else { 155 if(num == 0) puts("-1"); 156 else if(white[v]) puts("0"); 157 else { 158 printf("%d\n", Find(v)); 159 } 160 } 161 } 162 return 0; 163 }