给出一颗$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(点分治)的更多相关文章

  1. [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 ...

  2. CF1060E Sergey and Subway 思维

    分两种情况讨论 一种为奇数长为$L$的路径,在经过变化后,我们需要走$\frac{L}{2} + 1$步 一种为偶数长为$L$的路径,在变化后,我们需要走$\frac{L}{2}$步 那么,我们只需要 ...

  3. cf1060E. Sergey and Subway(树形dp)

    题意 题目链接 Sol 很套路的题 直接考虑每个边的贡献,最后再把奇数点的贡献算上 #include<bits/stdc++.h> #define Pair pair<int, in ...

  4. CF1060E Sergey and Subways 假的点分治

    题目传送门:http://codeforces.com/problemset/problem/1060/D 题意:给出$N$个点的一棵树,现在将距离为$2$的点之间连一条边,求所有点对之间最短路的和, ...

  5. 1060E Sergey and Subway(思维题,dfs)

    题意:给出一颗树,现在,给哪些距离为2的点对,加上一条边,问所有点对的距离和 题解:如果没有加入新的边,距离和就会等于每条边的贡献,由于是树,我们用点来代表点上面的边,对于每条边,它的贡献将是(子树大 ...

  6. CF 1060E. Sergey and Subway

    题目链接 题意:给你一棵树,然后连接两个有公共邻居的点,问你连完后,任意两点的距离之和. 一开始看这种题,还不怎么会做,借鉴了这位大佬的博客,get到了新技能,当我们求树上任意俩点的距离之时,可以转化 ...

  7. E. Sergey and Subway

    比赛时候写复杂了…… 我写的是 计算每个节点树内所有点到某个点的距离和. #include <bits/stdc++.h> using namespace std; typedef lon ...

  8. 【非原创】codeforces 1060E Sergey and Subway 【树上任意两点距离和】

    学习博客:戳这里 本人代码: 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 con ...

  9. Codeforces Round #513 游记

    Codeforces Round #513 游记 A - Phone Numbers 题目大意: 电话号码是8开头的\(1\)位数字.告诉你\(n(n\le100)\)个数字,每个数字至多使用一次.问 ...

随机推荐

  1. TCP socket心跳包示例程序

    在做游戏开发时,经常需要在应用层实现自己的心跳机制,即定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性. 在TCP socket心跳机制中,心跳包可以由服务器发送给客户端 ...

  2. SQL基础--&gt;层次化查询(START BY ... CONNECT BY PRIOR)

    --====================================================== --SQL基础-->层次化查询(START BY ... CONNECT BY ...

  3. HashTable源代码剖析

    <span style="font-size:14px;font-weight: normal;">public class Hashtable<K,V> ...

  4. Python 包的制作(__init__.py)

    如何制作一个自己的包:首先,需要创建一个文件夹,将其作为顶层包,在此文件夹内我们可以定义各个不同的子文件夹与 .py 文件作为各个子包与模块注意:在每个包文件夹下都需要有一个 __init__.py ...

  5. HDU 3065 病毒侵袭持续中(AC自己主动机)

    题目链接:http://acm.hdu.edu.cn/showproblem.php? pid=3065 Problem Description 小t非常感谢大家帮忙攻克了他的上一个问题.然而病毒侵袭 ...

  6. mysql有哪几种索引

    从数据结构角度 1.  B+树索引(O(log(n))) 2.  hash索引 3.  FULLTEXT索引 4.  R-Tree索引 从物理存储角度 1. 聚集索引 2.  非聚集索引 从逻辑角度 ...

  7. python day-15 匿名函数 sorted ()函数 filter()函数 map()函数 递归 二分法

    一.匿名函数 匿名函数的结构:变量   =  lamda  参数: 返回值 a  =  lamda  x : x*x       # x为参数,   : 后边的为函数体 print(a(x)) def ...

  8. BZOJ 2115: [Wc2011] Xor DFS + 线性基

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MB Description Input 第一行包含两个整数N和 M, 表示该无向图中 ...

  9. 小程序登录方式切换 不做url跳转

    var filegUP = require('../../utils/getUserPassword.js'); var filemd5 = require('../../utils/md5.min. ...

  10. LOJ#139. 树链剖分

    LOJ#139. 树链剖分 题目描述 这是一道模板题. 给定一棵$n$个节点的树,初始时该树的根为 1 号节点,每个节点有一个给定的权值.下面依次进行 m 个操作,操作分为如下五种类型: 换根:将一个 ...