正题

题目链接: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. Elastic_Search 和java的入门结合

    1, pom 文件添加依赖... 2, config 配置文件 3, 写接口文件

  2. springboot中添加事务注解

    1.首先在service层中的方法前添加@Transactional @Service public class UserService { @Autowired private UserMapper ...

  3. iphdr结构

    包含在/usr/src/linux/include/linux/ip.h 1 struct iphdr { 2 #if defined(__LITTLE_ENDIAN_BITFIELD) 3 __u8 ...

  4. Swagger2常用注解解析(轻松构建Swagger)

    Swagger2常用注解解析 一.SpringBoot集成Swagger2 二.常用注解解析 具体使用举例说明: 一.SpringBoot集成Swagger2 引入相关jar包 <!-- swa ...

  5. 跟我一起用unity做小地图!

    lol的小地图 转载爬虫请自重,未问先转没排面 不爱多做铺垫,小地图对于一些游戏来说多重要大家都懂,不然你也不会来看我这篇文章的,对不对? 话不多说,开搞! 一.主体功能 一般来说,游戏里的迷你地图都 ...

  6. MySQL-表迁移工具的选型-xtrabackup的使用

    1.1. 场景 有的时候test人员可能需要在测试库上比较新的数据,这时候只能是从生产库上面去那了.如果是小表还好实用mysqldump/mysqlpump就可以轻松的解决.但是,如果遇到了大表这将是 ...

  7. Python之uiautomation模块-获取CMD窗口中所打印的文字信息

    当我们想以自动化的方式操作软件,以提高办公或测试效率时,有许多成熟的工具,比如针对Web端应用的Selenium.针对移动端应用的Appium.那么,PC端(Windows)桌面应用,又改如何处理呢? ...

  8. 单片机学习(十二)1-Wire通信协议和DS18B20温度传感器

    目录 一.DS18B20 1. DS18B20简介 2. 电路原理图 3. 内部结构 内部完整结构框图 存储器结构 二.单总线(1-Wire BUS) 1. 单总线简介 2. 电路规范 3. 单总线的 ...

  9. 使用tasker定时打开一耳光应用

    比如现在要做一个:到9点钟自动打开"酷狗音乐"1.任务→点击"+"→填写"打开酷狗音乐"→点击"√"2.任务编辑→点击& ...

  10. 完全分布式Hadoop2.X的搭建

    准备工作: 安装jdk 克隆2台虚拟机完成后:新的2台虚拟机,请务必依次修改3台虚拟机的ip地址和主机名称[建议三台主机名称依次叫做:master.node1.node2 ](虚拟机的克隆,前面的博客 ...