正题

题目链接: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. Android系统编程入门系列之广播接收者BroadcastReceiver实现进程间通信

    在前边几篇关于Android系统两个重要组件的介绍中,界面Activity负责应用程序与用户的交互,服务Service负责应用程序内部线程间的交互或两个应用程序进程之间的数据交互.看上去这两大组件就能 ...

  2. WPF LiveChart 图表详解

    //参考网址:https://www.cnblogs.com/zh7791/p/12617961.html 本文主要介绍LiveChart.WPF 中的图表的使用方法 类: 数据绑定, 数据显示样式等 ...

  3. 【js】--获取开始时间 和 截止时间中间的所有时间

    1.工具函数  将[中国标准时间] 转换成 [年月日 时分秒] /* * timeStamp: 标准时间 例: 'Tue Sep 22 2020 00:00:00 GMT+0800 (中国标准时间)' ...

  4. wpf 的style

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x ...

  5. WPF简易聊天室

    一.聊天界面如下

  6. git cherry-pick 教程

    转自:http://www.ruanyifeng.com/blog/2020/04/git-cherry-pick.html 对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求. 这时分两 ...

  7. 回忆(一):反射中获得class对象的三种方法

    package reflex; /* * 反射:就是通过class文件对象 去使用该文件中的成员 * 变量,构造方法,成员方法. * * Person p = new Person(); p.使用 * ...

  8. xmake v2.5.7 发布,包依赖锁定和 Vala/Metal 语言编译支持

    xmake 是一个基于 Lua 的轻量级跨平台构建工具,使用 xmake.lua 维护项目构建,相比 makefile/CMakeLists.txt,配置语法更加简洁直观,对新手非常友好,短时间内就能 ...

  9. 将视图批量新增到PowerDesigner中并以model图表的形式展示

    1:需求 数据库中的所有视图大概64个左右,都需要新增到PowerDesigner中,以图表(model)的形式给展示出来,如下: 2:问题点: 由于2020年春节期间病毒的原因,我们需要远程办公,新 ...

  10. Install Docker Engine on CentOS 在CentOS 7 上安装Docker

    Install Docker Engine on CentOS OS Requirements 系统要求 To install Docker Engine,you need a maintained ...