正题

题目链接:https://www.luogu.com.cn/problem/P5666


题目大意

给出\(n\)个点的一棵树,对于每条边割掉后两棵树重心编号和。

\(1\leq T\leq 5,1\leq n\leq 299995\)


解题思路

编号和,所以应该是要我们枚举点然后求有多少条边割掉后它能当重心。

随便以一个点为根的话,对于一个点,割掉它子树外面的一条边,设割去的连通块大小为\(k\)那么需要满足,以及点\(x\)的最大子节点子树为\(f_x\)

\[\left\{\begin{matrix}2(n-k-s_x)\leq n-S\\2f_x\leq n-k\end{matrix}\right.
\]

移一下项就有

\[n-2s_x\leq k\leq n-2f_x
\]

但是子树里面就很难搞了,因为我们需要维护子树里所有子树的大小,其中一种方法是用线段树合并或者主席树像YbtOJ#662-交通运输这题一样搞。

很麻烦对啊吧,转换一下思路。其实有一个性质就是如果我们选择了原树的重心作为根节点,那么子节点无论如何割掉子树中的边也不会是重心。

所以这样就可以去掉这种麻烦的情况了。

只考虑前面那种,我们需要找到分割大小在\([n-2s_x,n-2f_x]\)这个区间的边,并且还要不在子树内。

如果不考虑不在子树内的话挺好搞,对于根节点到该节点的路径都是\(n-siz_x\),否则是\(siz_x\)丢进树状数组里查询就好了,边往下做边改树状数组就好了。

还要减去子树内的,好像还是要和上面一样用线段树合并?

我们可以用进入子树后的总共答案减去进入子树前的总共答案就是子树里面的答案了

这样好写很多,时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define lowbit(x) (x&-x)
using namespace std;
const ll N=3e5+10;
struct node{
ll to,next;
}a[N<<1];
ll T,n,ans,tot,rt,u,v;
ll siz[N],f[N],ls[N],t1[N],t2[N];
void addl(ll x,ll y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
void Change(ll *t,ll x,ll val){
x++;
while(x<=n+1){
t[x]+=val;
x+=lowbit(x);
}
return;
}
ll Ask(ll *t,ll x){
ll ans=0;x++;
if(x>=n+1)x=n+1;else if(x<0)x=0;
while(x){
ans+=t[x];
x-=lowbit(x);
}
return ans;
}
void dfs(ll x,ll fa){
siz[x]=1;f[x]=0;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa)continue;
dfs(y,x);siz[x]+=siz[y];
f[x]=max(f[x],siz[y]);
}
if(max(f[x],n-siz[x])<=n/2)rt=x;
return;
}
void calc(ll x,ll fa,bool flag){
Change(t1,siz[fa],-1);
Change(t1,n-siz[x],1);
ll tmp=Ask(t1,n-2*f[x])-Ask(t1,n-2*siz[x]-1);
tmp+=Ask(t2,n-2*f[x])-Ask(t2,n-2*siz[x]-1);
ans+=tmp*x;
ans+=rt*(siz[x]<=n-2*siz[flag?v:u]);
Change(t2,siz[x],1);
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa)continue;
calc(y,x,flag);
}
Change(t1,siz[fa],1);
Change(t1,n-siz[x],-1);
ans-=(Ask(t2,n-2*f[x])-Ask(t2,n-2*siz[x]-1))*x;
}
signed main()
{
scanf("%lld",&T);
while(T--){
memset(ls,0,sizeof(ls));
tot=rt=ans=u=v=0;
scanf("%lld",&n);
for(ll i=1;i<n;i++){
ll x,y;
scanf("%lld%lld",&x,&y);
addl(x,y);addl(y,x);
}
dfs(1,0);dfs(rt,0);
for(ll i=ls[rt];i;i=a[i].next){
ll y=a[i].to;
if(siz[y]>siz[u])v=u,u=y;
else if(siz[y]>siz[v])v=y;
}
memset(t1,0,sizeof(t1));
memset(t2,0,sizeof(t2));
for(ll i=1;i<=n;i++)Change(t1,siz[i],1);
for(ll i=ls[rt];i;i=a[i].next)
calc(a[i].to,rt,(a[i].to==u));
printf("%lld\n",ans);
}
return 0;
}

P5666-[CSP-S2019]树的重心【树状数组】的更多相关文章

  1. 【CSP模拟赛】仔细的检查(树的重心&树hash)

    题目描述 nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上.另一天nodgd更无聊,就又画了一张.  这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点 ...

  2. Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)

    题面 Bzoj 洛谷 题解 (除了代码均摘自喻队的博客,可是他退役了) 首先固定一棵树,枚举另一棵树,显然另一棵树只有与这棵树同构才有可能产生贡献 如果固定的树以重心为根,那么另一棵树最多就只有重心为 ...

  3. HDU4918 Query on the subtree 点分治+树状数组

    bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. At the very begining, the i-th ...

  4. [bzoj3155]Preprefix sum(树状数组)

    3155: Preprefix sum Time Limit: 1 Sec  Memory Limit: 512 MBSubmit: 1183  Solved: 546[Submit][Status] ...

  5. codeforces 685B Kay and Snowflake 树的重心

    分析:就是找到以每个节点为根节点的树的重心 树的重心可以看这三篇文章: 1:http://wenku.baidu.com/link?url=yc-3QD55hbCaRYEGsF2fPpXYg-iO63 ...

  6. Codeforces 980E The Number Games - 贪心 - 树状数组

    题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...

  7. poj 1655 树的重心 && define注意事项

    http://blog.csdn.net/acdreamers/article/details/16905653 题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果 ...

  8. Balancing Act(树的重心)

    传送门 Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14070   Accepted: 593 ...

  9. # [Poj 3107] Godfather 链式前向星+树的重心

    [Poj 3107] Godfather 链式前向星+树的重心 题意 http://poj.org/problem?id=3107 给定一棵树,找到所有重心,升序输出,n<=50000. 链式前 ...

  10. POJ 1655 Balancing Act【树的重心模板题】

    传送门:http://poj.org/problem?id=1655 题意:有T组数据,求出每组数据所构成的树的重心,输出这个树的重心的编号,并且输出重心删除后得到的最大子树的节点个数,如果个数相同, ...

随机推荐

  1. 【MyBatis系列5】MyBatis4大核心对象SqlSessionFactoryBuiler,SqlSessionFactory,SqlSession,Mapper

    前言 前几篇篇我们简单讲解了MyBatis的简单用法,以及一对一和一对多以及多对多的相关动态sql查询标签的使用,也提到了嵌套查询引发了N+1问题,以及延迟加载相关功能,本篇文章将会从MyBatis底 ...

  2. linux 常用的更新命令

    apt update apt install g++ apt install build_essential

  3. Mybatis出现错误org.apache.ibatis.executor.ExecutorException: No constructor found in

    错误显示没有发现构造器. 其实就是重写了构造器后,忘了补写一个默认的空参构造器了.此类的错误还经常出现在spring等这种大量使用反射的框架中.因为这些框架在调用反射的类后会默认调用默认的构造器 解决 ...

  4. mzy,struts学习(一)

    大家都在讲struts已经过时了,现在都是前后台分离,没有必要去学一个淘汰的框架,但是怎么讲呢?我觉得,struts能够流行那么多年,肯定有它的原因,肯定有很多优秀和好的地方,有一个指导过我的人给我讲 ...

  5. Go: 复合数据类型slice

    slice slice 表示用于相同类型元素的可变长度的序列. slice有三个属性:指针.长度和容量. 指针:slice存储数据的内部结构是数组,指针指向的是数组的地址 长度:保存slice中的元素 ...

  6. C# ThreadPool 分批处理数据,所有数据执行完再返回

    这是一个调用翻译数据的功能,所有数据一次性提交会造成后台服务压力大,接口反应时间也长. 所以做了一个分批处理,等待所有批次的数据调用接口都返回后再执行下一步. 1 /// <summary> ...

  7. 基于Linux系统Samba服务器的部署

    1.基础信息 用 Internet 文件系统 CIFS(Common Internet File System)是适用于MicrosoftWindows 服务器和客户端的标准文件和打印机共享系统信息块 ...

  8. docker run命令指定GPU多个显卡不生效的问题解决和代码示例

    问题描述:我有一个程序(app),需要用到显卡来跑.原本的部署方式 是直接修改程序的配置文件来指定要用到的显卡. 这是我服务器的显卡信息:总共3卡 分别是 0卡 ,1卡和2卡. [root@k8s-r ...

  9. GitHub+JSDelivr+PicGo+Typora免费白嫖高速稳定图床

    0. 初衷1. 创建 GitHub 仓库2. 使用 jsDelivr 进行 CDN 加速3. 使用PicGo上传图片4. Typora 配置 PicGo 上传 0. 初衷 平时写文章,经常需要插入图片 ...

  10. SpringBoot2.x+mybatis plus3.x集成Activit7版本

    最近在写一个开源项目ruoyi-vue-pro,暂时负责Activiti7工作流的搭建,接这个任务一个原因,是比较好奇Activiti7版本与先前的5.6版本究竟有什么区别,因为先前在工作当中,最开始 ...