100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > 【JZOJ 4639】Angel Beats!

【JZOJ 4639】Angel Beats!

时间:2022-10-19 19:18:16

相关推荐

【JZOJ 4639】Angel Beats!

Description

天使立华奏攻入了死后世界战线(SSS)的地下工会Guild,这是万分危急的时候。仲村由理指挥工会成员有条不紊地进行撤退工作。工会成员在Guild最深层工厂安放炸药需要很长的准备时间,需要有人来拖延立华奏的前进速度。但是他们并不清楚立华奏的具体位置,因此他们需要设立许多个防御点。

Guild的结构可以看成一棵有n 个节点的树,有时由理会得到立华奏的大概位置,可能在某两棵子树的任意一棵中,她就会找到Guild树(不一定要在两棵子树内)上的一个点,使得该点到两棵子树中所有点距离之和最小,即这两棵子树的重心(如果两棵子树有重合部分,那么取它们并集求重心)。

具体而言,你会得到Guild的结构(1为根),然后会有q个询问,向你查询点x子树和点y子树的重心,重心可能会有很多个,你只需要输出距离和即可。

抽象题意:给出一棵树,求两颗子树x,y的重心和所有子树内的点到重心的距离。

Solution

设每个点的儿子总数为 si ,所有儿子到点i的距离为 sli ,

首先有一个结论,同一个祖先q的儿子进行合并,如果重心不是当前的祖先,就只可能在 2∗sk>=si 的儿子k上,而且只可能在原儿子重心到q的路径上,

再运用点分治的找重心方法,即 max(sk)(k为q的儿子) 最小的点为重心,

那么加上上文的结论,不停的从儿子的重心往上跳,直到 max(sk)(k为q的儿子)>=其他子树中的点到q的距离左右为止,

左右的意思是我们需要把我们找到的这个点求一遍最优值后,把它往来路退一格,因为退一格的情况依旧有可能是重心,

以上的操作可以用倍增来实现,

还有一个结论:两颗无交集的子树,重心一定在较大的那一棵上,(这个显然吧)

同样的对于子树x,y(子树x>子树y),我们需要在点x到它的重心上找一点作为两颗子树的重心,(感性的理解一下)

这个跟上面的差不多,可以也用倍增;

有交集的直接输出即可;

计算距离的时候预处理一下全部点到每个点距离和子树内的点到祖先的距离即可;

复杂度: O(2nlog(n)+mlog(n)) ;

Code

有点恶心…

#include<iostream>#include<cstdio>#include<cstdlib>#define fo(i,a,b) for(int i=a;i<=b;i++)#define efo(i,q) for(int i=A[q];i;i=B[i][0])#define iff() if(B[i][1]!=fa)#define LCA(q,w) (LCA2(LCA1(q,a[w].c),LCA1(w,a[q].c)))#define H(q,w) (a[q].sl+1)using namespace std;const int N=100500,M=20;int read(int &n){char ch=' ';int q=0,w=1;for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());if(ch=='-')w=-1,ch=getchar();for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}int n,m,ans;struct qqww{int s,c,h,mx,hl,sl,ul;}a[N];int g[N][M+1];int B[2*N][2],A[N],B0;void link(int q,int w){B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w;}int dfs1(int q,int c,int fa){a[q].s=1;g[q][0]=fa;a[q].c=c;efo(i,q)iff(){a[q].s+=dfs1(B[i][1],c+1,q);a[q].sl+=a[B[i][1]].sl;}a[q].sl+=a[q].s-1;return a[q].s;}void dfsj(int q,int fa,int s){a[q].ul=s;efo(i,q)iff(){int w=B[i][1];dfsj(w,q,s+a[q].sl-a[w].sl-a[w].s+n-a[w].s);}}int LCA1(int q,int w){int i;while(a[q].c>w){for(i=0;a[g[q][i+1]].c>w;i++);q=g[q][i];}return q;}int LCA2(int q,int w){int i;while(q!=w){for(i=0;g[q][i+1]!=g[w][i+1];i++);q=g[q][i];w=g[w][i];}return q;}int JP(int q,int w,int tp){int I;while(w-a[q].s>a[q].mx&&a[q].c>a[tp].c){for(I=0;w-a[g[q][I+1]].s>a[g[q][I+1]].mx&&a[g[q][I+1]].c>a[tp].c;)I++;q=g[q][I];}return q;}void dfs2(int q,int fa){int s=0,w;a[q].h=q;a[q].hl=a[q].sl;efo(i,q)iff()dfs2(B[i][1],q),s=max(s,a[B[i][1]].s);a[q].mx=s;if(a[q].s==1)return;efo(i,q)iff()if(a[B[i][1]].s*2>=a[q].s){w=JP(a[B[i][1]].h,a[q].s,q);w=LCA1(a[B[i][1]].h,a[w].c+1);if(max(a[w].mx,a[q].s-a[w].s)<s){a[q].h=w,s=max(a[w].mx,a[q].s-a[w].s);a[q].hl=a[w].sl+(a[q].s-a[B[i][1]].s)*(a[w].c-a[q].c)+a[w].ul-(a[q].ul+(n-a[B[i][1]].s)*(a[w].c-a[q].c));}w=g[w][0];if(max(a[w].mx,a[q].s-a[w].s)<s){a[q].h=w,s=max(a[w].mx,a[q].s-a[w].s);a[q].hl=a[w].sl+(a[q].s-a[B[i][1]].s)*(a[w].c-a[q].c)+a[w].ul-(a[q].ul+(n-a[B[i][1]].s)*(a[w].c-a[q].c));}}}int main(){int q,w,e,_;read(n);fo(i,2,n)read(q),link(q,i);dfs1(1,1,0);fo(j,1,M)fo(i,1,n)g[i][j]=g[g[i][j-1]][j-1];dfsj(1,0,0);dfs2(1,0);read(_);while(_--){read(q),read(w);if(a[q].s<a[w].s)swap(q,w);e=LCA(q,w);if(e==q){printf("%d\n",a[q].hl);}else {int t=JP(a[q].h,a[q].s+a[w].s,q);ans=a[t].sl+(a[w].sl+a[w].s*(a[w].c+a[t].c-2*a[e].c))+(a[t].ul-(a[q].ul+(n-a[q].s)*(a[t].c-a[q].c)));t=LCA1(a[q].h,a[t].c+1);ans=min(ans,a[t].sl+(a[w].sl+a[w].s*(a[w].c+a[t].c-2*a[e].c))+(a[t].ul-(a[q].ul+(n-a[q].s)*(a[t].c-a[q].c))));printf("%d\n",ans);}}return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。