900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【NOIP模拟】Angel Beats!

【NOIP模拟】Angel Beats!

时间:2020-04-03 22:17:38

相关推荐

【NOIP模拟】Angel Beats!

Description

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

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

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

Solution

crazy_czy很喜欢这部番……卖广告

看到这题很懵逼啊,一个点x到他所在的子树y的所有节点的距离和怎么求,这个很简单,正难则反:

子树所有点到x距离和=所有点到x距离和−非子树所有点到x距离和

=所有点到x距离和−非子树所有点到子树根距离和−(n−子树大小)×dist(x,y)

=所有点到x距离和−(所有点到子树根距离和−子树所有点到子树根距离和)−(n−子树大小)×dist(x,y)

但是现在问题来了,怎么预处理出每个子树的重心?????

然后我这题就爆零了。

crazy_czy用了一大堆性质给我们讲。

结论1:两棵子树的重心一定在两棵子树各自重心连线的路径上。

结论2:在两棵子树size较大那棵内部一定能找到两棵子树重心。

结论2的推论:对于一个点x,令其size最大儿子为y,如果size(x)−1−size(y)≥size(y),那么子树x的重心一定为x,否则就一定在点y的子树内

结论2的推论证明十分的机制,因为如果size(x)-size(y)-1≥size(y),就说明重心不在最大的那个子数里面而在其他的子树的集合里面,那么最大的子树不符合,其他任意的子树也是同样的情况,那么最后所有子树集合的交际就是根节点x。

虽然知道了这些,代码———-

但是还是搞了很久,当时我向上倍增找重心一直找错,后来改了个巧妙的倍增。

本来倍增我存了很多什么最小值啊,位置啊之内的,然后其实每次倍增满足

size[y]-size[f[x][i]]>size[y]/2&&deep[f[x][i]]>deep[y]

这段东西就可以了,然后

if(size[y]-size[f[x][0]]<=size[y]/2&&size[big[f[x][0]]]<=size[y]/2)return f[x][0];return x;

在往上跳一位就是重心了。

表示调了好久……

Code

#include<iostream>#include<cstdio>#include<cstring>#include<cstdio>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)#define rep(i,a) for(i=first[a];i;i=next[i])using namespace std;const int maxn=100007;int i,j,k,l,t,n,m,ans;int first[maxn*2],next[maxn*2],last[maxn*2],num,bb,cc; int f[maxn][21],deep[maxn],g[maxn][21],size[maxn],zhong[maxn],big[maxn],wei[maxn][21],sum[maxn],zs[maxn];void add(int x,int y){last[++num]=y;next[num]=first[x];first[x]=num;last[++num]=x;next[num]=first[y];first[y]=num;}/*int lca(int x,int y){bb=0x7fffffff;cc=0;int i;if(deep[x]<deep[y])swap(x,y);fod(i,20,0)if(deep[f[x][i]]>deep[y])cc=(g[x][i]<bb)?wei[x][i]:cc,bb=min(bb,g[x][i]),x=f[x][i];if(deep[x]!=deep[y])cc=(g[x][0]<bb)?wei[x][0]:cc,bb=min(bb,g[x][i]),x=f[x][0];fod(i,20,0)if(f[x][i]!=f[y][i])cc=(g[x][i]<bb)?wei[x][i]:cc,bb=min(g[x][i],bb),cc=(g[y][i]<bb)?wei[y][i]:cc,bb=min(g[y][i],bb),x=f[x][i],y=f[y][i];if(x!=y)cc=(g[x][0]<bb)?wei[x][0]:cc,bb=min(g[x][0],bb),cc=(g[y][0]<bb)?wei[y][0]:cc,bb=min(g[y][0],bb);if(x!=y)return f[x][0];return x;}*/int lca(int x,int y){int i,k=0x7fffffff;if(deep[x]<deep[y])swap(x,y);fod(i,20,0)if(deep[f[x][i]]>deep[y])bb=(g[x][i]<k?wei[x][i]:bb),k=min(k,g[x][i]),x=f[x][i]; if(deep[x]!=deep[y])bb=(g[x][0]<k?wei[x][0]:bb),k=min(k,g[x][0]),x=f[x][0];fod(i,20,0)if(f[x][i]!=f[y][i])bb=(g[x][i]<k?wei[x][i]:bb),k=min(k,g[x][i]),bb=(g[y][i]<k?wei[y][i]:bb),k=min(k,g[y][i]),x=f[x][i],y=f[y][i];if(x!=y)bb=(g[x][0]<k?wei[x][0]:bb),k=min(k,g[x][0]),bb=(g[y][0]<k?wei[y][0]:bb),k=min(k,g[y][0]);if(x!=y)return f[x][0];else return x;}int bei(int x,int y){int i,k=0x7fffffff;if(deep[x]<deep[y])swap(x,y);fod(i,20,0)if(size[y]-size[f[x][i]]>size[y]/2&&deep[f[x][i]]>deep[y])x=f[x][i];if(size[y]-size[f[x][0]]<=size[y]/2&&size[big[f[x][0]]]<=size[y]/2/*&&deep[f[x][0]]>deep[y]*/)return f[x][0];return x;}void dfs(int x,int y){int i,k=0;deep[x]=deep[y]+1;size[x]=1;sum[1]+=deep[x]-1;if(x==38){ans=ans;}rep(i,x){if(last[i]!=y){dfs(last[i],x);size[x]+=size[last[i]];if(size[last[i]]>k){k=size[last[i]];big[x]=last[i];}zs[x]+=zs[last[i]]+size[last[i]];}}}void dfs1(int x,int y){int i,o=n-size[x];g[x][0]=sum[x];wei[x][0]=x;if(x==38){ans=ans;}rep(i,x){if(last[i]!=y){sum[last[i]]=sum[x]+(n-size[last[i]])-size[last[i]];dfs1(last[i],x);}}}void fh(int x,int y){int i,o=n-size[x];rep(i,x){if(last[i]!=y){fh(last[i],x);}}if(size[x]==1){zhong[x]=x;return;}if(x==38){ans=ans;}if(size[big[x]]<=size[x]-size[big[x]]-1)zhong[x]=x;else{/* if(size[x]-size[zhong[big[x]]]<=size[x]/2){zhong[x]=zhong[big[x]];}else{*/int o=bei(zhong[big[x]],x);zhong[x]=o; // }}}int suan(int x,int y){int o=0;o=sum[x]-(sum[y]-zs[y])-(n-size[y])*(deep[x]-deep[y]);}int main(){// freopen("fan.out","w",stdout);scanf("%d",&n);fo(i,2,n){scanf("%d",&f[i][0]);add(f[i][0],i);}dfs(1,0);memset(g,127,sizeof(g));dfs1(1,0);fo(j,1,20){fo(i,1,n){f[i][j]=f[f[i][j-1]][j-1];wei[i][j]=(g[i][j-1]<g[f[i][j-1]][j-1])?wei[i][j-1]:wei[f[i][j-1]][j-1];g[i][j]=min(g[i][j-1],g[f[i][j-1]][j-1]);}}fh(1,0);for(scanf("%d",&m);m;m--){scanf("%d%d",&k,&l);int o=lca(k,l);int u=deep[k]-2*deep[o]+deep[l];int ss=size[k]+size[l];if(size[k]<size[l])swap(k,l);if(k==o)ss=size[k];int z=zhong[k];fod(i,20,0)if(ss-size[f[z][i]]>ss/2&&deep[f[z][i]]>deep[k])z=f[z][i];if(ss-size[f[z][0]]<=ss/2&&size[big[f[z][0]]]<=ss/2/*&&deep[f[z][0]]>=deep[k]&&deep[f[z][0]]>deep[o]*/)z=f[z][0];if(k==o)ans=suan(z,k);else ans=suan(z,k)+(u+deep[z]-deep[k])*size[l]+zs[l];printf("%d\n",ans);}}

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