给出一颗$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. Intel processor brand names-Xeon,Core,Pentium,Celeron----Atom

    http://en.wikipedia.org/wiki/Intel_atom Intel Atom From Wikipedia, the free encyclopedia   (Redirect ...

  2. Android的Message Pool是个什么鬼,Message Pool会否引起OOM——源代码角度分析

    引言 Android中,我们在线程之间通信传递通常採用Android的消息机制,而这机制传递的正是Message. 通常.我们使用Message.obtain()和Handler.obtainMess ...

  3. log开启与屏蔽的一种调式方式

    #ifndef _LOGGING_H #define _LOGGING_H #define deg printf #ifdef ENABLE_TRACING #define ENTER() do { ...

  4. window批处理-5 start

    作用 又一次启动一个单独窗体.在新窗体中运行命令 格式 start [/w] FileName demo bat: @echo off echo 在新窗体中打开txt文件.并等待新窗体正常退出(exi ...

  5. leetcode -day17 Path Sum I II &amp; Flatten Binary Tree to Linked List &amp; Minimum Depth of Binary Tree

    1.  Path Sum Given a binary tree and a sum, determine if the tree has a root-to-leaf path such tha ...

  6. Python2.7安装教程

    作者:zhanhailiang 日期:2014-11-16 [root@~/software]# yum install bzip* [root@~/software]# wget http://ww ...

  7. Scaling with Microservices and Vertical Decomposition

    Scaling with Microservices and Vertical Decomposition – dev.otto.de https://dev.otto.de/2014/07/29/s ...

  8. React 编码

    https://github.com/Minwe/style-guide/blob/master/React.js.md https://github.com/planningcenter/react ...

  9. [RK3288][Android6.0] 调试笔记 --- pmu(rk818)寄存器读写【转】

    本文转载自:http://blog.csdn.net/kris_fei/article/details/76919134 Platform: Rockchip OS: Android 6.0 Kern ...

  10. POJ2516 Minimum Cost —— 最小费用最大流

    题目链接:https://vjudge.net/problem/POJ-2516 Minimum Cost Time Limit: 4000MS   Memory Limit: 65536K Tota ...