bzoj 3572 分类: bzoj 2015-03-29 22:23 45人阅读 评论(0) 收藏
2015-03-29 22:23
435 查看
虚树:包含了给定点,并收缩了不分叉边的连通子图。
http://www.kuangbin.net/archives/bzoj3572
虚树的构建:
将所有询问点按照dfs序排一遍序,然后,依次加入栈中,若枚举的节点h[i]与栈顶元素的s[top] 的LCA fa的深度比栈顶元素深度小,s[top-1]向s[top]连接一条边,栈顶弹出,fa与h[i]都加入栈中。就这样,一颗虚树建立出来了。
/article/6445312.html
虚树的dp:
分几种情况来讨论:
1.首先,虚树中没有父亲的点p一定是最高的点,有大小为n-size[p]的点与他共用最近点。
2.每个虚树上的点和他没在虚树上的子树肯定会共用一个最近点这个我们只要用其总的size减去在虚树中的size最后统计答案即可。
3.对于虚树某一对父子i,fa,若他们共用一对最近点,则他们在树上的链上点也一定共用这个最近点。
4.若并不共用最近点,肯定有某一段与fa共用最近点,另一段与i共用最近点。因此我们需要找到这个分界点p。由于p到i最近点的距离与p到fa最近点的距离尽可能的接近,所以有dis(i,p)=(near[fa]-near[i]+dis(i,fa))/2,这样得出来的点是最接近的,并且考虑了不能整除的情况,但是仍然需要特判一些情况——p到i与p到fa的距离一样近,我们就需要比较他们点的大小,适当的调整p的位置。
/article/6445314.html
代码是抄的,别问我为什么,就是自己写不出吧。。。
#include<map> #include<string> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> //bzoj3572 const int MAXN = 300005 ,logN = 20 ,INF = 1<<30; int n , head[MAXN] = {0}, ml = 0; struct edgetype{int v,next;}edge[MAXN<<1] = {0}; int fa[MAXN][logN] = {0}, dep[MAXN] = {0}, size[MAXN] = {0}; int DFN[MAXN] = {0}, dl = 0; int q ; void build(int a) { DFN[a]= ++dl; dep[a] = dep[fa[a][0]]+1; size[a] = 1; for(int i = head[a]; i ; i = edge[i].next) { int p = edge[i].v; if(p == fa[a][0])continue; fa[p][0] = a; build(p); size[a] += size[p]; } return; } void prelca() { for(int j = 1 ;j < logN; j++) for(int i = 1; i <= n ; i++) fa[i][j] = fa[fa[i][j-1]][j-1]; } void newedge(int u,int v) { ++ml;edge[ml].v = v; edge[ml].next = head[u]; head[u] = ml; } int h0[MAXN],h[MAXN],ans[MAXN]; int vfa[MAXN],t[MAXN],val[MAXN]; int stack[MAXN],w[MAXN]; std::pair<int,int>g[MAXN]; #define Wei first #define Num second #define Mp(x,y) std::make_pair(x,y) int getLCA(int u,int v) { if(dep[u]<dep[v])std::swap(u,v);//dep[u]>=dep[v] for(int i = logN - 1; i >= 0;i--) if(dep[fa[u][i]] >= dep[v]) u = fa[u][i]; if(u == v)return u; for(int i = logN - 1; i >= 0; i--) if(fa[u][i]!=fa[v][i]) u = fa[u][i], v = fa[v][i]; return fa[u][0]; } int upto(int u ,int des) { for(int i = logN - 1; i >= 0;i--) if(dep[fa[u][i]] >= des) u = fa[u][i]; return u; } bool cmp(const int a,const int b){return (DFN[a]<DFN[b]);} void solve() { int m ,tot = 0; scanf("%d",&m); for(int i = 1; i <= m; i++) { scanf("%d",&h[i]); h0[i] = h[i]; t[++tot] = h[i]; g[h[i]] = Mp(0,h[i]); ans[h[i]] = 0; } std::sort(h + 1,h + m + 1,cmp); int top = 0; for(int i = 1; i <= m; i++) if(!top) vfa[stack[++top] = h[i]] = 0; else { int p = h[i], lca = getLCA(p,stack[top]); while(dep[stack[top]] > dep[lca]) { if(dep[stack[top-1]] <= dep[lca]) vfa[stack[top]] = lca; top--; } if(stack[top] != lca) { t[++tot] = lca; g[lca] = Mp(INF , 0); vfa[lca] = stack[top]; stack[++top] = lca; } vfa[p] = lca; stack[++top] = p; } //build the virtual tree std::sort(t + 1 , t + tot + 1 ,cmp); for(int i = 1 ; i <= tot ; i++) { int p = t[i]; val[p] = size[p]; if(i!=1)w[p] = dep[p] - dep[vfa[p]]; } for(int i = tot; i > 1 ; i--) { int p = t[i], fi = vfa[p]; g[fi] = std::min(Mp(g[p].Wei+w[p],g[p].Num),g[fi]); } for(int i = 2; i <= tot; i++) { int p = t[i], fi = vfa[p]; g[p] = std::min(Mp(g[fi].Wei+w[p],g[fi].Num),g[p]); }//BFS for(int i = 1 ;i <= tot; i++) { int p = t[i], fi = vfa[p]; if(i == 1) ans[g[p].Num] += size[1] - size[p]; else { int x = upto(p,dep[fi]+1), sum = size[x] - size[p]; val[fi] -= size[x]; if(g[fi].Num == g[p].Num)ans[g[p].Num] += sum; else { int tmp = g[fi].Wei + g[p].Wei + w[p]; int mid = dep[p] - ((tmp>>1) - g[p].Wei); if((tmp&1)==0 && g[p].Num > g[fi].Num) mid++; int y = size[upto(p,mid)] - size[p]; ans[g[p].Num] += y; ans[g[fi].Num] += sum - y; } } }//Dp for(int i = 1 ; i <= tot; i++) ans[g[t[i]].Num] += val[t[i]]; for(int i = 1 ; i <= m ; i++) printf("%d ",ans[h0[i]]); printf("\n"); } int main() { #ifndef ONLINE_JUDGE freopen("worldtree.in","r",stdin); freopen("worldtree.out","w",stdout); #endif scanf("%d",&n); for(int i = 1; i < n ; i++) { int a,b;scanf("%d%d",&a,&b); newedge(a,b);newedge(b,a); } fa[1][0] = 0; build(1);prelca(); scanf("%d",&q); while(q--)solve(); #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); #endif }
相关文章推荐
- bzoj 1502 计算几何 分类: bzoj 2015-03-09 22:23 54人阅读 评论(0) 收藏
- leetCode(45):Min Stack 分类: leetCode 2015-07-20 08:34 139人阅读 评论(0) 收藏
- bzoj 4011 分类: bzoj 2015-05-28 14:11 33人阅读 评论(0) 收藏
- bzoj2301 分类: bzoj 2015-05-30 23:14 33人阅读 评论(0) 收藏
- bzoj 1004 分类: bzoj 2015-06-29 21:31 25人阅读 评论(0) 收藏
- bzoj 3211 分类: bzoj 2015-08-07 18:00 8人阅读 评论(0) 收藏
- bzoj2440 分类: bzoj 2015-05-30 23:15 29人阅读 评论(0) 收藏
- bzoj 2006 分类: bzoj 2015-05-31 17:18 29人阅读 评论(0) 收藏
- [eclipse]Unhandled event loop exception | No more handles 分类: eclipse 2014-08-29 09:45 282人阅读 评论(0) 收藏
- bzoj 4010 [HNOI 2015 Day1 T3] 分类: bzoj 2015-05-27 22:25 31人阅读 评论(0) 收藏
- bzoj 1999 分类: bzoj noip 2015-08-07 23:37 15人阅读 评论(0) 收藏
- bzoj 2038 分类: bzoj templates 2015-03-26 20:28 41人阅读 评论(0) 收藏
- bzoj 2743 分类: bzoj 2015-08-07 18:22 9人阅读 评论(0) 收藏
- iphone获取屏幕尺寸以及状态栏 分类: ios开发 2015-03-29 21:35 198人阅读 评论(0) 收藏
- bzoj2820 分类: bzoj 2015-06-02 14:02 26人阅读 评论(0) 收藏
- sgu 193 分类: sgu 2015-03-11 18:38 45人阅读 评论(0) 收藏
- bzoj 2821 分类: bzoj 2015-08-07 18:38 11人阅读 评论(0) 收藏
- Android 之自定义控件样式在d… 分类: Android开发 2014-05-30 10:56 45人阅读 评论(0) 收藏
- bzoj 1030 分类: bzoj templates 2015-08-06 17:34 10人阅读 评论(0) 收藏
- bzoj 1036 [LCT version] 分类: templates bzoj 2015-08-06 22:05 20人阅读 评论(0) 收藏