P5002 专心OI - 找祖先

给定一棵有根树(\(n \leq 10000\)),\(M \leq 50000\) 次询问, 求以 \(x\) 为 \(LCA\) 的点对个数


错误日志: 看下面


Solution

设点 \(u\) 的子树大小为 \(size[u]\)

现询问以 \(u\) 为 \(LCA\) 的点对个数

设 \(u\) 的子节点为 \(v_{1}, v_{2},...,v_{m}\)

我们现在统计点对中一个点在 \(v_{1}\) 内的答案数

一个点在 \(v_{1}\) 内, 另一个点要么是 \(u\) 要么在剩下的子节点子树内选一个

所以总数为 \(size[u] - size[v_{1}]\) 个

乘法原理 \(v_{1}\) 子树中所有答案为 \(size[v] * (size[u] - size[v])\)

每个子节点点都是这样

最后加上一个 \((u, u)\) 即可

然后这样 \(85pnts\)

看数据范围, 最不优情况 \(O(NM)\)

然后发现 \(M > N\)

询问次数多于点个数?

这提示我们像记忆化那样记下答案

回头想想这样的复杂度为 \(O(N)\) , 这是一棵树, 边数和点数不会差太多, 复杂度有保障

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define LL long long
#define REP(i, x, y) for(LL i = (x);i <= (y);i++)
using namespace std;
LL RD(){
LL out = 0,flag = 1;char c = getchar();
while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
return flag * out;
}
const LL maxn = 200019,INF = 1e9 + 19, M = 1e9 + 7;
LL head[maxn],nume = 1;
struct Node{
LL v,dis,nxt;
}E[maxn << 3];
void add(LL u,LL v,LL dis){
E[++nume].nxt = head[u];
E[nume].v = v;
E[nume].dis = dis;
head[u] = nume;
}
LL num, root, na;
LL size[maxn], fa[maxn];
LL mem[maxn];
void dfs(LL u, LL F){
size[u] = 1;
for(LL i = head[u];i;i = E[i].nxt){
LL v = E[i].v;
if(v == F)continue;
fa[v] = u;
dfs(v, u);
size[u] = (size[u] + size[v]) % M;
}
}
void init(){
num = RD(), root = RD(), na = RD();
REP(i, 1, num - 1){
LL u = RD(), v = RD();
add(u, v, 1), add(v, u, 1);
}
dfs(root, -1);
}
void solve(){
while(na--){
LL ans = 0, u = RD(), temp = size[u];
if(mem[u]){printf("%lld\n", mem[u]);continue;}
for(LL i = head[u];i;i = E[i].nxt){
LL v = E[i].v;
if(v == fa[u])continue;
ans = (ans + ((size[v] * (temp - size[v])) % M + M) % M) % M;
temp = ((temp - size[v]) % M + M) % M;
}
ans = (ans * 2 + 1) % M;
mem[u] = ans;
printf("%lld\n", ans);
}
}
int main(){
init();
solve();
return 0;
}

P5002 专心OI - 找祖先的更多相关文章

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

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

  2. luogu P5002 专心OI - 找祖先

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

  3. 【洛谷 5002】专心OI - 找祖先 (树上计数)

    专心OI - 找祖先 题目背景 \(Imakf\)是一个小蒟蒻,他最近刚学了\(LCA\),他在手机\(APP\)里看到一个游戏也叫做\(LCA\)就下载了下来. 题目描述 这个游戏会给出你一棵树,这 ...

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

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

  5. 洛谷【P5004 专心OI - 跳房子】 题解

    题目链接 https://www.luogu.org/problem/P5004 洛谷 P5004 专心OI - 跳房子 Imakf有一天参加了PINO 2017 PJ组,他突然看见最后一道题 他十分 ...

  6. HDOJ 题目2475 Box(link cut tree去点找祖先)

    Box Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submi ...

  7. [luogu5004]专心OI - 跳房子【矩阵加速+动态规划】

    传送门:https://www.luogu.org/problemnew/show/P5004 分析 动态规划转移方程是这样的\(f[i]=\sum^{i-m-1}_{j=0}f[j]\). 那么很明 ...

  8. 【LuoguP5004】 专心OI - 跳房子

    首先这是一道计数类DP,那我们得先推式子,经过瞎掰乱凑,经过认真分析,我们可以得到这样的方程 F(N)=F(0)+F(1)+....+F(N-M-1) 所有F初值为1,F(1)=2 ANS=F(N+M ...

  9. 「P5004」专心OI - 跳房子 解题报告

    题面 把\(N\)个无色格子排成一行,选若干个格子染成黑色,要求每个黑色格子之间至少间隔\(M\)个格子,求方案数 思路: 矩阵加速 根据题面,这一题似乎可以用递推 设第\(i\)个格子的编号为\(i ...

随机推荐

  1. Linux内核分析——可执行程序的装载

    链接的过程 首先运行C预处理器cpp,将C的源程序(a.c)翻译成ASCII码的中间文件(a.i) 接着C编译器ccl,将a.i翻译成ASCII汇编语言文件a.s 接着运行汇编器as,将a.s翻译成可 ...

  2. 《Linux内核设计与实现》读书笔记三

    Chapter 18 调 试 18.1 准备开始 1.准备工作: 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 2.执行foo就会让程序立即产生核心信息转储(dump core). ...

  3. 20150421 作业5 四则运算 测试与封装 5.1 5.2(doing)

    结伴队友:王佳寧,他的博客地址:http://www.cnblogs.com/paopaotai/ 5.2 黑白盒測試 測試項目名稱 黑盒測試 測試人員 葉子鵬&王佳寧 測試編號 測試頁面 測 ...

  4. Maven的课堂笔记1

    1 什么是maven? Maven是一个跨平台的项目管理工具,主要用于基于java平台的项目构建,依赖管理. Clean  compile  test  package  install   run ...

  5. dip vs di vs ioc

    https://stackoverflow.com/questions/6766056/dip-vs-di-vs-ioc https://docs.microsoft.com/en-us/aspnet ...

  6. [转帖]JavaEE中Web服务器、Web容器、Application服务器区别及联系

    JavaEE中Web服务器.Web容器.Application服务器区别及联系 https://www.cnblogs.com/vipyoumay/p/5853694.html 在JavaEE 开发W ...

  7. [日常工作] Linux与Windows的连接访问以及数据共享等方法 vncserver smb xshell xftp winscp mount等

    日常办公机器是用 windows, 但是越来越多的测试和工作需求需要使用linux. 这里以最常用的系统centos为例进行说明 1. 远程连接 ssh的方式 建议使用xmange 系列的 xshel ...

  8. insertBefore(),appendChild()创建添加列表实例

    定义: insertBefore() 方法在您指定的已有子节点之前插入新的子节点. 语法: 父级.insertBefore(新的子节点,指定的已有子节点) 实例: <input id=" ...

  9. C++ 动态内存分配(6种情况,好几个例子)

    1.堆内存分配 : C/C++定义了4个内存区间: 代码区,全局变量与静态变量区,局部变量区即栈区,动态存储区,即堆(heap)区或自由存储区(free store). 堆的概念: 通常定义变量(或对 ...

  10. Linux基础学习(7)--用户和用户组管理

    第七章——用户和用户组管理 一.用户配置文件 1.用户信息文件/etc/passwd: (1)用户管理简介:所以越是对服务器安全性要求高的服务器,越需要建立合理的用户权限等级制度和服务器操作规范.   ...