CF1060E Sergey and Subway(点分治)
给出一颗$N$个节点的树,现在我们**在原图中**每个不直接连边但是中间只间隔一个点的两个点之间连一条边. 比如**在原图中**$u$与$v$连边,$v$与$w$连边,但是$u$与$w$不连边,这时候我们就需要连一条$u$与$v$的边. 现在我们需要求出新图中每一个点对$(i,j)\ (1 \leq i \leq j \leq N)$的经过的边数和.
因为实在太菜了不会树形dp的只好用点分了……
(点分是个好东西所有树的题目都可以暴力艹过去)
首先,设原点对之间距离为$dis$,如果$dis$是奇数,那么新的距离为$(dis>>1)+1$,否则为$dis>>1$
我们考虑如何计算经过当前根节点的路径对答案的贡献
我们设已经dfs过的子树中有$cnt0$条长度为偶数的链,$dis0$这些链的每一条的长度除以二之和,同理$cnt1$和$dis1$表示长度为奇数的链的条数和每一条链的长度除以二加一的和
简单来讲$dis1$和$dis0$分别表示将原$dis$按上面的方法转化后的答案
然后考虑当前子树$v$,设$v$中的以上信息分别为,$cnt[0],cnt[1],dis[0],dis[1]$
然后就是路径的两两组合分别计入答案就是了
顺便注意因为两条奇数路径合起来变为偶数,所以相当于每一条路径的长度都要减一
然后别忘了加上子树单独的贡献
//minamoto
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,:;}
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=2e5+;
int head[N],Next[N<<],ver[N<<],tot;
int cnt[];ll dis[],ans=;
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
int sz[N],son[N],size,vis[N],rt,n;
void findrt(int u,int fa){
sz[u]=,son[u]=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(vis[v]||v==fa) continue;
findrt(v,u),sz[u]+=sz[v],cmax(son[u],sz[v]);
}
cmax(son[u],size-sz[u]);
if(son[u]<son[rt]) rt=u;
}
void dfs(int u,int fa,int d){
d&?(++cnt[],dis[]+=((d>>)+)):(++cnt[],dis[]+=(d>>));
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa&&!vis[v]) dfs(v,u,d+);
}
}
void getans(int u){
int cnt0=,cnt1=;ll dis0=,dis1=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(vis[v]) continue;
cnt[]=cnt[]=,dis[]=dis[]=;
dfs(v,u,);
// ans+=dis[1]*dis1-cnt[1]*cnt1;
// ans+=dis[1]*dis0;
// ans+=dis[0]*dis1;
// ans+=dis[0]*dis0;
ans+=dis[]*cnt1+dis1*cnt[]-1ll*cnt1*cnt[];
ans+=dis[]*cnt0+dis0*cnt[];
ans+=dis[]*cnt1+dis1*cnt[];
ans+=dis[]*cnt0+dis0*cnt[];
ans+=dis[]+dis[];
cnt0+=cnt[],cnt1+=cnt[];
dis0+=dis[],dis1+=dis[];
}
}
void solve(int u){
vis[u]=,getans(u);
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(vis[v]) continue;
size=sz[v],rt=,findrt(v,u);
solve(rt);
}
}
int main(){
// freopen("testdata.in","r",stdin);
n=read();
for(int i=,u,v;i<n;++i)
u=read(),v=read(),add(u,v),add(v,u);
son[rt=]=n+,size=n,findrt(,);
solve(rt);
printf("%I64d\n",ans);
return ;
}
CF1060E Sergey and Subway(点分治)的更多相关文章
- [CF1060E]Sergey and Subway[树dp]
题意 给出 \(n\) 个点的树,求 \(\sum_{i=1}^n{\sum_{j=i}^n{\lceil \frac{dis(i,j)}{2} \rceil}}\) . \(n\leq 2 \tim ...
- CF1060E Sergey and Subway 思维
分两种情况讨论 一种为奇数长为$L$的路径,在经过变化后,我们需要走$\frac{L}{2} + 1$步 一种为偶数长为$L$的路径,在变化后,我们需要走$\frac{L}{2}$步 那么,我们只需要 ...
- cf1060E. Sergey and Subway(树形dp)
题意 题目链接 Sol 很套路的题 直接考虑每个边的贡献,最后再把奇数点的贡献算上 #include<bits/stdc++.h> #define Pair pair<int, in ...
- CF1060E Sergey and Subways 假的点分治
题目传送门:http://codeforces.com/problemset/problem/1060/D 题意:给出$N$个点的一棵树,现在将距离为$2$的点之间连一条边,求所有点对之间最短路的和, ...
- 1060E Sergey and Subway(思维题,dfs)
题意:给出一颗树,现在,给哪些距离为2的点对,加上一条边,问所有点对的距离和 题解:如果没有加入新的边,距离和就会等于每条边的贡献,由于是树,我们用点来代表点上面的边,对于每条边,它的贡献将是(子树大 ...
- CF 1060E. Sergey and Subway
题目链接 题意:给你一棵树,然后连接两个有公共邻居的点,问你连完后,任意两点的距离之和. 一开始看这种题,还不怎么会做,借鉴了这位大佬的博客,get到了新技能,当我们求树上任意俩点的距离之时,可以转化 ...
- E. Sergey and Subway
比赛时候写复杂了…… 我写的是 计算每个节点树内所有点到某个点的距离和. #include <bits/stdc++.h> using namespace std; typedef lon ...
- 【非原创】codeforces 1060E Sergey and Subway 【树上任意两点距离和】
学习博客:戳这里 本人代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 con ...
- Codeforces Round #513 游记
Codeforces Round #513 游记 A - Phone Numbers 题目大意: 电话号码是8开头的\(1\)位数字.告诉你\(n(n\le100)\)个数字,每个数字至多使用一次.问 ...
随机推荐
- mysql 安装与启动
1.下载mysql installer 2.安装 一直点next,直到finish. 3.安装时的配置 安装完后,选择立即开始配置. 选择standard configuration 勾选安装mysq ...
- 腾讯云图片鉴黄集成到C# SQL Server 怎么在分页获取数据的同时获取到总记录数 sqlserver 操作数据表语句模板 .NET MVC后台发送post请求 百度api查询多个地址的经纬度的问题 try{}里有一个 return 语句,那么紧跟在这个 try 后的 finally {}里的 code 会 不会被执行,什么时候被执行,在 return 前还是后? js获取某个日期
腾讯云图片鉴黄集成到C# 官方文档:https://cloud.tencent.com/document/product/641/12422 请求官方API及签名的生成代码如下: public c ...
- val();html();.text()区别 setInterval与setTimeout的区别
val();html();.text()区别 对于innerHTML 属性,几乎所有的元素都有innerHTML属性,它是一个字符串,用来设置或获取位于对象起始和结束标签内的HTML.(获取HTM ...
- 浅谈JavaScript的函数表达式(递归)
递归函数,在前面的博客中已经简单的介绍了.递归函数是一个通过函数名称在函数内部调用自身的函数.如下: function fac(num){ if(num<1){ return 1; } else ...
- 文件宝iOS/iPhone/iPad客户端简介
App Store地址:https://itunes.apple.com/cn/app/id1023365565?mt=8 文件宝-装机必备的文件管家,专业的rar-zip 解压工具,局域网看片神器, ...
- Codeforces Round #Pi (Div. 2) C. Geometric Progression
C. Geometric Progression time limit per test 1 second memory limit per test 256 megabytes input stan ...
- (linux)platform_driver_probe与platform_driver_register的区别
[驱动注册]platform_driver_register()与platform_device_register() 设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册 ...
- Uboot中start.S源码的指令级的详尽解析【转】
本文转载自:http://www.crifan.com/files/doc/docbook/uboot_starts_analysis/release/html/uboot_starts_analys ...
- How to create a List of ValueTuple?
ValueTuple需要通过NuGet安装System.ValueTuple https://docs.microsoft.com/en-us/dotnet/csharp/tuples?view=ne ...
- poj 1789 Truck History 解题报告
题目链接:http://poj.org/problem?id=1789 题目意思:给出 N 行,每行7个字符你,统计所有的 行 与 行 之间的差值(就是相同位置下字母不相同),一个位置不相同就为1,依 ...