专心OI - 找祖先

题目背景

\(Imakf\)是一个小蒟蒻,他最近刚学了\(LCA\),他在手机\(APP\)里看到一个游戏也叫做\(LCA\)就下载了下来。

题目描述

这个游戏会给出你一棵树,这棵树有\(N\)个节点,根结点是\(R\),系统会选中\(M\)个点\(P_1,P_2...P_M\),要\(Imakf\)回答有多少组点对\((u_i,v_i)\)的最近公共祖先是\(P_i\)。\(Imakf\)是个小蒟蒻,他就算学了\(LCA\)也做不出,于是只好求助您了。

\(Imakf\)毕竟学过一点\(OI\),所以他允许您把答案模 \((10^9+7)\)

输入输出格式

输入格式:

第一行 \(N , R , M\).

此后\(N-1\)行 每行两个数\(a,b\) 表示\(a,b\)之间有一条边

此后\(1\)行 \(M\)个数 表示\(P_i\)

输出格式:

\(M\)行,每行一个数,第ii行的数表示有多少组点对\((u_i,v_i)\)的最近公共祖先是\(P_i\)

输入输出样例

输入样例#1:

7 1 3
1 2
1 3
2 4
2 5
3 6
3 7
1 2 4

输出样例#1:

31
7
1

说明

对于询问1:

(1,1) (1,2) (1,3) (1,4) (1,5) (1,6) (1,7) (2,1) (2,3) (2,6) (2,7) (3,1) (3,2) (3,4) (3,5) (4,1) (4,3) (4,6) (4,7) (5,1) (5,3) (5,6) (5,7) (6,1) (6,2) (6,4) (6,5) (7,1) (7,2) (7,4) (7,5)共31组

对于询问2:

(2,2) (2,4) (2,5) (4,2) (4,5) (5,2) (5,4)共7组

对于询问3:

(4,4)共1组

数据范围

\(N\leq10000,M\leq50000\)

题解

看到这是洛谷新出的题,看着有点思路就做了。

我在\(dfs\)时就预处理出了\(ans\)数组,即为每个点的答案,所以时间复杂度是\(O(max(n,m))\)

对于每个点\(x\),我们可以把答案分成跨过\(x\)的和没有跨过\(x\)的方案两部分。

没有跨过x的部分:

很显然,其中一个点一定是\(x\),所以这部分的答案为\(x\)的\(siz\)大小的\(2\)倍\(-1\)(因为是点对并且(1,1)算一种)。

即\(ans1=2*siz[x]-1\).

跨过\(x\)的部分:

根据乘法原理,所有\(x\)的儿子\(son_i\)的\(siz\)大小相乘即为这部分的答案。

设\(x\)一共有\(k\)棵子树即

\[ans2=\sum_{i=1}^{k}\sum_{j=1}^{k}siz[son[i]]*siz[son[j]] \\=\sum_{i=1}^{k}siz[son[i]]*(siz[x]-1)\\=(siz[x]-1)*(siz[x]-1)
\]

但是我们会发现不对,因为我们算重了一部分,就是\((i==j)\)的部分。

所以我们还要减去\(\sum_{i=1}^{k}siz[son[i]]^2\).

所以\(ans2=(siz[x]-1)^2-\sum_{i=1}^{k}siz[son[i]]^2\)

综上:

\[Ans=ans1+ans2\\=2*siz[x]-1+(siz[x]-1)^2-\sum_{i=1}^{k}siz[son[i]]^2\\=siz[x]^2-\sum_{i=1}^{k}siz[son[i]]^2
\]

我们只需要维护一下每个点子树的\(siz[son[i]]^2\)的和即可获得答案。

吐槽一句:这题Ans最大是\(N^2\),居然要去取模。。。。

code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#define N 10005
#define R register
using namespace std;
template<typename T>inline void read(T &a){
char c=getchar();T x=0,f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
a=f*x;
}
int n,rt,m,tot,p;
int siz[N],ans[N],h[N],sum[N];
struct node{
int nex,to;
}edge[N<<1];
inline void add(R int u,R int v){
edge[++tot].nex=h[u];
edge[tot].to=v;
h[u]=tot;
}
inline void dfs(R int x,R int f){
siz[x]=1;
for(R int i=h[x];i;i=edge[i].nex){
R int xx=edge[i].to;
if(xx==f)continue;
dfs(xx,x);
siz[x]+=siz[xx];
sum[x]+=siz[xx]*siz[xx];
}
ans[x]=siz[x]*siz[x]-sum[x];
}
int main(){
read(n);read(rt);read(m);
for(R int i=1,u,v;i<=n-1;i++)
read(u),read(v),add(u,v),add(v,u);
dfs(rt,0);
while(m--){
read(p);
printf("%d\n",ans[p]);
}
return 0;
}

【洛谷 5002】专心OI - 找祖先 (树上计数)的更多相关文章

  1. 洛谷P5002 专心OI - 找祖先

    题目概括 题目描述 这个游戏会给出你一棵树,这棵树有\(N\)个节点,根结点是\(R\),系统会选中\(M\)个点\(P_1,P_2...P_M\). 要Imakf回答有多少组点对\((u_i,v_i ...

  2. P5002 专心OI - 找祖先

    P5002 专心OI - 找祖先 给定一棵有根树(\(n \leq 10000\)),\(M \leq 50000\) 次询问, 求以 \(x\) 为 \(LCA\) 的点对个数 错误日志: 看下面 ...

  3. luogu P5002 专心OI - 找祖先

    题目描述 这个游戏会给出你一棵树,这棵树有NN个节点,根结点是RR,系统会选中MM个点P_1,P_2...P_MP 1 ​ ,P 2 ​ ...P M ​ ,要Imakf回答有多少组点对(u_i,v_ ...

  4. [luogu5002]专心OI - 找祖先

    [传送门] 我们还是先将一下算法的步骤,待会再解释起来方便一点. 算法步骤 首先我们算出每个子树的\(size\). 我们就设当前访问的节点 然后我们就得到了当前这个节点的答案是这个树整个的\(siz ...

  5. 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增

    倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...

  6. 洛谷 1600 (NOIp2016) 天天爱跑步——树上差分

    题目:https://www.luogu.org/problemnew/show/P1600 看TJ:https://blog.csdn.net/clove_unique/article/detail ...

  7. 【BZOJ4566_洛谷3181】[HAOI2016]找相同字符(SAM)

    自己yy的方法yyyyyyyy着就A了,写篇博客庆祝一下. 题目: 洛谷3181 分析: SAM(可能是)模板题(不会SAM的同学戳我:[知识总结]后缀自动机的构建). 对\(s1\)建出SAM,用\ ...

  8. bzoj 4592(洛谷 4344) [Shoi2015]脑洞治疗仪——线段树上二分

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4592 1操作就是用线段树来二分找到第一个有 k 个0的位置. 在洛谷上A了,与暴力和网上题解 ...

  9. 【洛谷P3398】仓鼠找sugar

    画个图就能多少看出些规律 证明借鉴一下大牛的题解: 设从A到B,经过的深度最小的点为X 同理,C,D的为Y 题目是一个点从A出发到B 一个从C出发到D 那么从A到B可以分解成 先从A到X 再从X到B. ...

随机推荐

  1. 混合开发之DSBridge(同时支持Android和iOS)

    什么是 Javascript bridge 随着h5的不断普及及优化,以及移动端对动态化的需求越来越大,开发者经常需要在app中嵌入一些网页,然后会在web和native之间进行交互,如传递数据,调用 ...

  2. java-tip-各种Map的区别及如何选择

    这里主要讨论这三种:HashMap.LinkedHashMap.TreeMap 1. HashMap是常规的哈希表,查询以及插入的性能最好,如果没有特殊要求,应该使用这个 2. LinkedHashM ...

  3. Python使用struct处理二进制(pack和unpack用法)

    转载自:http://www.cnblogs.com/gala/archive/2011/09/22/2184801.html 这篇文章写的很好,所以无耻的转了.. 有的时候需要用python处理二进 ...

  4. Python爬虫实战五之模拟登录淘宝并获取所有订单

    经过多次尝试,模拟登录淘宝终于成功了,实在是不容易,淘宝的登录加密和验证太复杂了,煞费苦心,在此写出来和大家一起分享,希望大家支持. 温馨提示 更新时间,2016-02-01,现在淘宝换成了滑块验证了 ...

  5. JDK1.6 1.7 1.8 多版本windows安装 执行命令java -version 版本不变的问题

    现在Windows的java安装已经没有解压版本,Oracle官方也不会再提供了,只有安装程序 所以每当安装一次JDK,都会将 java.exe.javaw.exe.javaws.exe三个可执行文件 ...

  6. Java Persistence with MyBatis 3(中文版) 第一章 MyBatis入门

    本章将涵盖以下话题: ž  MyBatis是什么? ž  为什么选择MyBatis? ž  MyBatis安装配置 ž  域模型样例 1.1 MyBatis是什么 MyBatis是一个简化和实现了Ja ...

  7. redis 缓存用户账单策略

    最近项目要求分页展示用户账单列表,为提高响应使用redis做缓存,用到的缓存策略和大家分享一下. 需求描述:展示用户账单基本信息以时间倒序排序,筛选条件账单类型(所有,订单收入.提现.充值...). ...

  8. Hadoop(分布式系统基础架构)---Hive与HBase区别

    对于刚接触大数据的用户来说,要想区分Hive与HBase是有一定难度的.本文将尝试从其各自的定义.特点.限制.应用场景等角度来进行分析,以作抛砖引玉之用.  Hive是什么? Apache Hive是 ...

  9. Why won't JRockit find my classes

    This is the second post by Mattis, diving deep into JVM specifics. NoClassDefFoundErrors are a drag. ...

  10. JavaScript学习总结——转

    JavaScript学习总结(一)——JavaScript基础 JavaScript学习总结(二)——逻辑Not运算符详解 JavaScript学习总结(三)——逻辑And运算符详解 JavaScri ...