P5666-[CSP-S2019]树的重心【树状数组】
正题
题目链接:https://www.luogu.com.cn/problem/P5666
题目大意
给出\(n\)个点的一棵树,对于每条边割掉后两棵树重心编号和。
\(1\leq T\leq 5,1\leq n\leq 299995\)
解题思路
编号和,所以应该是要我们枚举点然后求有多少条边割掉后它能当重心。
随便以一个点为根的话,对于一个点,割掉它子树外面的一条边,设割去的连通块大小为\(k\)那么需要满足,以及点\(x\)的最大子节点子树为\(f_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]树的重心【树状数组】的更多相关文章
- 【CSP模拟赛】仔细的检查(树的重心&树hash)
题目描述 nodgd家里种了一棵树,有一天nodgd比较无聊,就把这棵树画在了一张纸上.另一天nodgd更无聊,就又画了一张. 这时nodgd发现,两次画的顺序是不一样的,这就导致了原本的某一个节点 ...
- Bzoj3197/洛谷3296 [SDOI2013]刺客信条assassin(树的重心+树Hash+树形DP+KM)
题面 Bzoj 洛谷 题解 (除了代码均摘自喻队的博客,可是他退役了) 首先固定一棵树,枚举另一棵树,显然另一棵树只有与这棵树同构才有可能产生贡献 如果固定的树以重心为根,那么另一棵树最多就只有重心为 ...
- 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 ...
- [bzoj3155]Preprefix sum(树状数组)
3155: Preprefix sum Time Limit: 1 Sec Memory Limit: 512 MBSubmit: 1183 Solved: 546[Submit][Status] ...
- codeforces 685B Kay and Snowflake 树的重心
分析:就是找到以每个节点为根节点的树的重心 树的重心可以看这三篇文章: 1:http://wenku.baidu.com/link?url=yc-3QD55hbCaRYEGsF2fPpXYg-iO63 ...
- Codeforces 980E The Number Games - 贪心 - 树状数组
题目传送门 传送点I 传送点II 传送点III 题目大意 给定一颗有$n$个点的树,$i$号点的权值是$2^{i}$要求删去$k$个点,使得剩下的点仍然连通,并且总权值和最大,问删去的所有点的编号. ...
- poj 1655 树的重心 && define注意事项
http://blog.csdn.net/acdreamers/article/details/16905653 题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果 ...
- Balancing Act(树的重心)
传送门 Balancing Act Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 14070 Accepted: 593 ...
- # [Poj 3107] Godfather 链式前向星+树的重心
[Poj 3107] Godfather 链式前向星+树的重心 题意 http://poj.org/problem?id=3107 给定一棵树,找到所有重心,升序输出,n<=50000. 链式前 ...
- POJ 1655 Balancing Act【树的重心模板题】
传送门:http://poj.org/problem?id=1655 题意:有T组数据,求出每组数据所构成的树的重心,输出这个树的重心的编号,并且输出重心删除后得到的最大子树的节点个数,如果个数相同, ...
随机推荐
- Anaconda Pycharm 是怎么个事儿?
前言 许多人学习Python的经历可能很相似,写程序没有问题,最后却被各种环境困扰. 不论你是Python小白,还是学习Python有一段时间了.都可以认真的看一下ヾ(≧▽≦*)o 这篇文章让你对An ...
- HTML <form> 标签的 method 属性
定义和用法 method 属性规定如何发送表单数据(表单数据发送到 action 属性所规定的页面). 表单数据可以作为 URL 变量(method="get")或者 HTTP p ...
- 13.SpringMVC之全局异常
我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发.测试通过手段减少运行时异常的发生.在开发中,不管是dao层 ...
- BeanUtils中的自动类型转换(二)
javabean package entity; import java.util.Date; /** * 一个测试用: * student,javaBean * @author mzy * 一个标准 ...
- springcloud超时重试机制的先后顺序
https://blog.csdn.net/zzzgd_666/article/details/83314833
- python 截屏操作
方法1: 用pyscreenshot,https://pypi.org/project/pyscreenshot/ 方法2:用autopy,https://pypi.org/project/autop ...
- 痞子衡嵌入式:MCUXpresso Config Tools初体验(Pins, Clocks, Peripherals)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso Config Tools三大件(Pins, Clocks, Peripherals). 不知道大家有没有这样的感受 ...
- sublime text 3 中文排序插件
ST3 的排序不支持中文按拼音排序,所以需要搞一个插件来支持这一特性 pypinyin 这个库可以把中文转成拼音,可惜不支持 python3.3,而 ST3 内置的 python 就是 3.3 我系统 ...
- JAVA 之 每日一记 之 算法 ( 长按键入 )
题目详解: 你的朋友正在使用键盘输入他的名字 name.偶尔,在键入字符 c 时,按键可能会被长按,而字符可能被输入 1 次或多次. 你将会检查键盘输入的字符 typed.如果它对应的可能是你的朋友的 ...
- 优化技术专题-线程间的高性能消息框架-深入浅出Disruptor的使用和原理
前提概要 简单回顾 jdk 里的队列: 阻塞队列: ArrayBlockingQueue主要通过:数组(Object[])+ 计数器(count)+ ReetrantLock的Condition (n ...