虚树(HNOI2014 世界树)
开坑虚树
2018.3.24这个坑可能需要闲置一段时间qaq
2018.5.17妈妈我也会写这题了QwQ
首先建出虚树,网上模板很多,不再详述(其实就是懒得写)
然后我们发现对于虚树上的一条父子边,显然对应一坨东西。具体来说大概是size[u的v方向第一个儿子] - size[v]
然后先处理出虚树上的点每个点属于哪个关键点,先用儿子更新父亲然后用父亲更新儿子
那么对于父子边上的一坨点,如果父子属于同一个关键点,显然把这一坨东西加上去就好了
如果不属于,令分界点为k,即满足k和k以上的一坨都是父亲节点管的,令d[i]表示i的深度,那么d[v]-d[k]+d2=d[k]-d[u]+d1
d1和d2代表u和v到各自关键点的距离。所以d[k] = 1/2*(d[v] + d[u] + d2 - d1)。当后面这坨(不乘二分之一)是偶数的时候,显然k对应的这一个或者一坨点到两个关键点距离一样,这时候判一下标号大小
然后细节处理好就行了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<algorithm> 3 #include<set> 4 #include<vector> 5 using namespace std; 6 int n , qu; 7 struct gg 8 { 9 int num , g; 10 }p[300005]; 11 int dft = 0; 12 vector<int> E[300005]; 13 vector<int> E2[300005]; 14 vector<int> s; 15 set<int> q; 16 int dep[300005]; 17 bool tag[300005]; 18 int f[300005][20] , dfn[300005] , r[300005] , size[300005] , ans[300005] , gs[300005]; 19 pair<int,int> wh[300005]; 20 int g[300005] , root; 21 inline int read() 22 { 23 char ch = getchar(); 24 int s = 0; 25 while(!('0' <= ch && ch <= '9')) ch = getchar(); 26 while('0' <= ch && ch <= '9'){ 27 s = s * 10 + ch - '0'; 28 ch = getchar(); 29 } 30 return s; 31 } 32 void dfs(int fa,int u,int d) 33 { 34 dfn[u] = ++dft;size[u] = 1; 35 dep[u] = d; 36 if(fa)f[u][0] = fa; 37 else f[u][0] = u; 38 for(int i = 0;i < E[u].size();i++){ 39 if(E[u][i] != fa) {dfs(u , E[u][i] , d + 1);size[u] += size[E[u][i]];} 40 } 41 r[u] = dft; 42 return; 43 } 44 void pre() 45 { 46 for(int i = 1;i <= 19;i++){ 47 for(int j = 1;j <= n;j++){ 48 f[j][i] = f[f[j][i - 1]][i - 1]; 49 } 50 } 51 return; 52 } 53 int query(int u,int v) 54 { 55 if(dep[u] < dep[v]) swap(u , v); 56 for(int i = 19;i >= 0;i--){ 57 if(dep[f[u][i]] >= dep[v]) u = f[u][i]; 58 } 59 if(u == v) return u; 60 for(int i = 19;i >= 0;i--){ 61 if(f[u][i] != f[v][i]){ 62 u = f[u][i] , v = f[v][i]; 63 } 64 } 65 return f[u][0]; 66 } 67 bool cmp(gg a,gg b) 68 { 69 return a.g < b.g; 70 } 71 inline void add(int u,int v){/*printf("ADD %d %d\n",u,v);*/E2[u].push_back(v);E2[v].push_back(u);return;} 72 void dfs2(int fa,int u) 73 { 74 g[u] = size[u]; 75 if(tag[u]) wh[u] = pair<int,int>{u , 0}; 76 for(int i = 0;i < E2[u].size();i++){ 77 if(E2[u][i] != fa) dfs2(u , E2[u][i]); 78 } 79 if(wh[fa].first == 0 || wh[fa].second > dep[u] - dep[fa] + wh[u].second){ 80 wh[fa].first = wh[u].first;wh[fa].second = dep[u] - dep[fa] + wh[u].second; 81 } 82 else if(wh[fa].second == dep[u] - dep[fa] + wh[u].second && wh[fa].first > wh[u].first) wh[fa].first = wh[u].first; 83 return; 84 } 85 void dfs3(int fa,int u) 86 { 87 for(int i = 0;i < E2[u].size();i++){ 88 if(E2[u][i] != fa){ 89 if(wh[E2[u][i]].second > wh[u].second + dep[E2[u][i]] - dep[u]){wh[E2[u][i]].first = wh[u].first;wh[E2[u][i]].second = wh[u].second + dep[E2[u][i]] - dep[u];} 90 else if(wh[E2[u][i]].second == wh[u].second + dep[E2[u][i]] - dep[u] && wh[E2[u][i]].first > wh[u].first) wh[E2[u][i]].first = wh[u].first; 91 dfs3(u , E2[u][i]); 92 } 93 } 94 return; 95 } 96 int get(int u,int v) 97 { 98 for(int i = 19;i >= 0;i--){ 99 if(dep[f[u][i]] > v) u = f[u][i]; 100 } 101 return u; 102 } 103 int jump(int u,int k) 104 { 105 int s = 0; 106 while(k){ 107 if(k&1) u = f[u][s]; 108 k >>= 1;s++; 109 } 110 return u; 111 } 112 void calc(int fa,int u) 113 { 114 ans[wh[u].first]++;g[u]--; 115 for(int i = 0;i < E2[u].size();i++){ 116 if(E2[u][i] != fa){ 117 int v = E2[u][i]; 118 if(wh[u].first == wh[v].first){int t = size[get(v , u)] - size[v];ans[wh[u].first] += t;g[u] -= t;} 119 else if(dep[u] != dep[v] - 1){ 120 int d1 = wh[u].second , d2 = wh[v].second , gq; 121 int dk = (dep[v] + dep[u] - d1 + d2); 122 if(dk % 2 == 0 && wh[u].first > wh[v].first) dk -= 2; 123 int t = jump(v , dep[v] - (dk>>1) - 1);gq = size[t] - size[v];ans[wh[v].first] += gq;g[u] -= gq; 124 gq = size[get(t , u)] - size[t];ans[wh[u].first] += gq;g[u] -= gq; 125 } 126 calc(u , v); 127 g[u] -= size[v]; 128 } 129 } 130 if(g[u]) ans[wh[u].first] += g[u]; 131 return; 132 } 133 void solve() 134 { 135 dfs2(0 , root); 136 dfs3(0 , root); 137 ans[wh[root].first] = size[1] - size[root]; 138 calc(0 , root); 139 return; 140 } 141 int main() 142 { 143 n = read(); 144 for(int i = 1;i < n;i++){ 145 int x , y; 146 x = read() , y = read(); 147 E[x].push_back(y); 148 E[y].push_back(x); 149 } 150 dfs(0 , 1 , 1); 151 pre(); 152 qu = read(); 153 while(qu--){ 154 int m = read();q.clear();root = 0; 155 for(int i = 1;i <= m;i++){ 156 int x = read();tag[x] = 1; 157 p[i].num = x;p[i].g = dfn[x];gs[i] = x; 158 if(dep[x] < dep[root] || root == 0) root = x; 159 } 160 sort(p + 1 , p + m + 1 , cmp); 161 vector<int>::iterator it; 162 for(int i = 1;i <= m;i++){ 163 if(!s.size() || r[s[s.size() - 1]] >= p[i].g){s.push_back(p[i].num);q.insert(p[i].num);continue;} 164 int lca = query(p[i].num , s[s.size() - 1]); 165 if(dep[lca] < dep[root]) root = lca; 166 while(s.size() > 1 && dep[s[s.size() - 2]] > dep[lca]){it = s.end();it--;add(*it , s[s.size() - 2]);s.erase(it);} 167 it = s.end();it--;add(*it , lca);s.erase(it); 168 if(q.find(lca) == q.end()){s.push_back(lca);q.insert(lca);} 169 s.push_back(p[i].num);q.insert(p[i].num); 170 } 171 while(s.size() > 1){it = s.end();it--;add(*it , s[s.size() - 2]);s.erase(it);} 172 s.clear(); 173 solve(); 174 for(int i = 1;i <= m;i++) printf("%d ",ans[gs[i]]); 175 printf("\n"); 176 set<int>::iterator it2 = q.begin(); 177 while(it2 != q.end()) {E2[*it2].clear();tag[*it2] = ans[*it2] = g[*it2] = 0;wh[*it2] = pair<int,int>{0 , 0};it2++;} 178 } 179 return 0; 180 }