洛谷P3258 松鼠的新家
树上差分
这应该是一道很简单的树上差分了。。就是问每个点被覆盖了多少次。
要注意我们最后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 松鼠的新家的更多相关文章
- 洛谷 P3258 松鼠的新家 题解
题面 貌似这道题暴力加玄学优化就可以AC? 下面是正解: 1.树链剖分: 我们在u到v之间都放一个糖果,可以将松鼠它家u到v的糖果数都加1.每一次将a[i]到a[i+1] (a数组是访问顺序)的节点加 ...
- 洛谷 [P3258] 松鼠的新家
树上差分 对于一条路径 \(u->v\) 来说,设 \(t=LCA(u,v)\) ,d[]为差分数组 ,则有 d[u]++;d[v]++;d[t]--;d[fa[t]]--; 注意:题目中所给的 ...
- 洛谷P3258松鼠的新家
题目传送门 恩,很明显的一个树剖题,配合树上差分其实也并不难,不过无奈蒟蒻树剖还没那么熟练,而且树上差分也做的少,所以这题愣是做了一中午......唉,果然我还是太菜了.恩,具体做法在代码中解释吧: ...
- P3258 松鼠的新家
松鼠的新家 洛谷链接 尽管标签是省选/NOI-,但提交的通过率已经高到三分之一了. 但它仍旧是一个省选/NOI-的题. 大致题意就是按输入的顺序走一棵树,看每个节点经过多少次.问题就相当于把一条链上的 ...
- 【题解】P3258松鼠的新家
[题解][P3258 JLOI2014]松鼠的新家 树链剖分板子题. 总结一点容易写错的地方吧: if(d[top[u]]<d[top[v]]) swap(u,v);注意是\(top\). 在\ ...
- Luogu P3258 松鼠的新家(树链剖分+线段树/树状数组)
题面 题解 这种题目一看就是重链剖分裸题,还是区间修改,单点查询,查询之前在遍历时要记一个\(delta\),因为这一次的起点就是上一次的终点,不需要放糖,所以可以用\(BIT\)来写,但我写完\(m ...
- BZOJ3631:[JLOI2014]松鼠的新家——题解
http://www.lydsy.com/JudgeOnline/problem.php?id=3631 https://www.luogu.org/problemnew/show/P3258 松鼠的 ...
- 洛谷 P3258 BZOJ 3631 [JLOI2014]松鼠的新家
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
随机推荐
- Vue(一)之ES6基础
01-先了解ES6语法 1.声明变量let和const <script type="javascript"> //es5声明变量 var 先声明,后赋值 //var a ...
- Codeforces Round #521 (Div. 3)
B 题过的有些牵强,浪费了很多时间,这种题一定想好思路和边界条件再打,争取一发过. D 题最开始读错题,后面最后发现可以重复感觉就没法做了,现在想来,数据量大,但是数据范围小枚举不行,二分还是可以的 ...
- Wannafly summer camp Day6 - D 区间权值
这道题实在是不该,我在化式子的时候,多此一举,把式子进行累加,导致自己当时化的式子是错的,这样导致自己卡了很久,也没想到好的思路,赛后重新分析一波,感觉巨™简单...难受的一逼. 这道题的关键在于,W ...
- Python-类的继承与派生
python中类的继承分为:单继承和多继承 class ParentClass1: #定义父类 pass class ParentClass2: #定义父类 pass class SubClass1( ...
- SPA单页面优缺点
优点: 1.体验好,不刷新,减少 请求 数据ajax异步获取 页面流程: 2.前后端分离 3.减轻服务端压力 4.共用一套后端程序代码,设配多端 缺点: 1.首屏加载过慢: 2.SEO 不利于搜索引 ...
- FPGA中边沿触发和电平触发
边沿触发和电平触发基本就是触发器和锁存器的区别: 触发器是边沿触发,只有当时钟上升(或下降)的一瞬间,触发器会读取并锁存输入信号.输出信号仅在时钟信号上升(或下降)的一瞬间会发生变化. 锁存器是电 ...
- nginx的The page you are looking for is temporarily unavailable错误解决办法
访问网站时出现如下错误,如下图: 检查php fastcgi进程数,如下图: 输出0则表示fastcgi进程数够大,修改scgi_params文件,如下图: 然后重启php-fpm和nginx,重新访 ...
- PAT L2-016 愿天下有情人都是失散多年的兄妹
https://pintia.cn/problem-sets/994805046380707840/problems/994805061769609216 呵呵.大家都知道五服以内不得通婚,即两个人最 ...
- [转帖]再次提醒Google Chrome用户应尽快升级浏览器到72.0.3626.121
再次提醒Google Chrome用户应尽快升级浏览器到72.0.3626.121 转帖地址: https://www.cnbeta.com/articles/tech/825591.htm 国内离线 ...
- outline,box-shadow,border-radius小例子
<!doctype html> <html> <head> <meta charset="utf-8"> <title> ...