树上差分

这应该是一道很简单的树上差分了。。就是问每个点被覆盖了多少次。

要注意我们最后dfs后,要把除第一个节点以外的所有点的-1,因为有些点作为起点和终点覆盖了两次,按照题目意思是不用覆盖两次的。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
using namespace std;
typedef long long ll;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int X = 0, w = 0; char ch = 0;
while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
return w ? -X : X;
}
inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
template<typename T>
inline T max(T x, T y, T z){ return max(max(x, y), z); }
template<typename T>
inline T min(T x, T y, T z){ return min(min(x, y), z); }
template<typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
return ans;
}
const int N = 300005;
int n, s[N], cnt, head[N], depth[N], p[N][20], t, val[N];
bool vis[N];
struct Edge { int v, next; }edge[N<<1]; void addEdge(int a, int b){
edge[cnt].v = b, edge[cnt].next = head[a], head[a] = cnt ++;
} void dfs(int s, int fa){
depth[s] = depth[fa] + 1;
p[s][0] = fa;
for(int i = 1; i <= t; i ++){
p[s][i] = p[p[s][i - 1]][i - 1];
}
for(int i = head[s]; i != -1; i = edge[i].next){
int u = edge[i].v;
if(u == fa) continue;
dfs(u, s);
}
} int lca(int x, int y){
if(depth[x] < depth[y]) swap(x, y);
for(int i = t; i >= 0; i --){
if(depth[p[x][i]] >= depth[y]) x = p[x][i];
}
if(x == y) return y;
for(int i = t; i >= 0; i --){
if(p[x][i] != p[y][i]) x = p[x][i], y = p[y][i];
}
return p[y][0];
} void dfs(int s){
vis[s] = true;
for(int i = head[s]; i != -1; i = edge[i].next){
int u = edge[i].v;
if(vis[u]) continue;
dfs(u);
val[s] += val[u];
}
} int main(){ full(head, -1);
n = read();
for(int i = 0; i < n; i ++) s[i] = read();
for(int i = 0; i < n - 1; i ++){
int u = read(), v = read();
addEdge(u, v), addEdge(v, u);
}
t = (int)(log(n) / log(2)) + 1;
dfs(s[0], 0);
for(int i = 0; i < n - 1; i ++){
val[s[i]] ++, val[s[i + 1]] ++;
int f = lca(s[i], s[i + 1]);
val[f] --, val[p[f][0]] --;
}
dfs(s[0]);
for(int i = 1; i < n; i ++) val[s[i]] --;
for(int i = 1; i <= n; i ++) printf("%d\n", val[i]);
return 0;
}

洛谷P3258 松鼠的新家的更多相关文章

  1. 洛谷 P3258 松鼠的新家 题解

    题面 貌似这道题暴力加玄学优化就可以AC? 下面是正解: 1.树链剖分: 我们在u到v之间都放一个糖果,可以将松鼠它家u到v的糖果数都加1.每一次将a[i]到a[i+1] (a数组是访问顺序)的节点加 ...

  2. 洛谷 [P3258] 松鼠的新家

    树上差分 对于一条路径 \(u->v\) 来说,设 \(t=LCA(u,v)\) ,d[]为差分数组 ,则有 d[u]++;d[v]++;d[t]--;d[fa[t]]--; 注意:题目中所给的 ...

  3. 洛谷P3258松鼠的新家

    题目传送门 恩,很明显的一个树剖题,配合树上差分其实也并不难,不过无奈蒟蒻树剖还没那么熟练,而且树上差分也做的少,所以这题愣是做了一中午......唉,果然我还是太菜了.恩,具体做法在代码中解释吧: ...

  4. P3258 松鼠的新家

    松鼠的新家 洛谷链接 尽管标签是省选/NOI-,但提交的通过率已经高到三分之一了. 但它仍旧是一个省选/NOI-的题. 大致题意就是按输入的顺序走一棵树,看每个节点经过多少次.问题就相当于把一条链上的 ...

  5. 【题解】P3258松鼠的新家

    [题解][P3258 JLOI2014]松鼠的新家 树链剖分板子题. 总结一点容易写错的地方吧: if(d[top[u]]<d[top[v]]) swap(u,v);注意是\(top\). 在\ ...

  6. Luogu P3258 松鼠的新家(树链剖分+线段树/树状数组)

    题面 题解 这种题目一看就是重链剖分裸题,还是区间修改,单点查询,查询之前在遍历时要记一个\(delta\),因为这一次的起点就是上一次的终点,不需要放糖,所以可以用\(BIT\)来写,但我写完\(m ...

  7. BZOJ3631:[JLOI2014]松鼠的新家——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=3631 https://www.luogu.org/problemnew/show/P3258 松鼠的 ...

  8. 洛谷 P3258 BZOJ 3631 [JLOI2014]松鼠的新家

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...

  9. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

随机推荐

  1. 蛙蛙推荐: TensorFlow Hello World 之平面拟合

    tensorflow 已经发布了 2.0 alpha 版本,所以是时候学一波 tf 了.官方教程有个平面拟合的类似Hello World的例子,但没什么解释,新手理解起来比较困难. 所以本文对这个案例 ...

  2. pycharm 常用快捷键操作

    #最重要的快捷键 1. ctrl+shift+A:万能命令行 2. shift两次:查看资源文件 #新建工程第一步操作 1. module设置把空包分层去掉,compact empty middle ...

  3. Django的model form组件

    前言 首先对于form组件通过全面的博客介绍,对于form我们应该知道了它的大致用法,这里我们需要明确的一点是,我们定义的form与model其实没有什么关系,只是在逻辑上定义form的时候字段名期的 ...

  4. 阿里云作为yum源操作

    阿里云提供的yum镜像地址为:https://opsx.alibaba.com/mirror 找到自己的使用系统,点击帮助,可以查看更换说明 替换centOS的yum源,如下图 具体操作: CentO ...

  5. Dapper-小型ORM之王(C#.NET)

    ORM:对象关系映射器,它直接将数据库映射到C#对象. 有很多ORM框架可用,Dapper是其中之一,被称为ORM之王. 下面是Dapper主要的一些功能: 速度快,性能好; 更少的代码行 对象映射 ...

  6. c++入门之再话内存和引用

    此处没有代码,仅仅讨论一些这样的问题:我们为何使用引用?在哪里使用引用? 首先从函数的角度思考?:函数进行一般参数传递的时候,是怎么样传递的?普通类型的参数传递,是将传递的实参复制一份,到另一个内存空 ...

  7. 使用mysql,sql语言删除冗余信息

    这是表,我们需要操作的就是删除除了学号不同,其它信息都相同的冗余信息 思路:删除表格class3中的冗余的stu_id信息,那么接下来我们应该去筛选哪些stu_id信息是冗余的, 此时我们想到的就是利 ...

  8. WinForm 进度条

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. Python_架构、同一台电脑上两个py文件通信、两台电脑如何通信、几十台电脑如何通信、更多电脑之间的通信、库、端口号

    1.架构 C/S架构(鼻祖) C:client  客户端 S:server  服务器 早期使用的一种架构,目前的各种app使用的就是这种架构,它的表现形式就是拥有专门的app. B/S架构(隶属于C/ ...

  10. html js 表单提交前检测数据

    通过使用form的onsibmit来控制是否提交数据 返回值为真是提交,其他不变,示例如下: JS部分 function check() { var newPwd = document.getElem ...