P3258 [JLOI2014]松鼠的新家
文章目录
- 题意:
- 题解:
- 树上差分
- 代码:
- 树链剖分
- 代码:
P3258 [JLOI2014]松鼠的新家
题意:
n个点,n-1条边,给出每个点的拜访顺序,问每个点经过几次(最后一次移动不算拜访)
题解:
题意明确后就很好做了,对于给定的x和y,我们只需要分别将x和y到lca(x,y)经过的点加一即可
但是这样直接做肯定不行
有两个方法:
- 树上差分
- 树链剖分
树上差分
参考题解
我们先考虑对于数组,我们指定连续一段加一
我们现在对a2到a6区间进行加一
现在处理差分数组,我们对a2加一,对a7减一
差分属猪的定义:a[i] = a[i-1] + 差分数组[i]
也就是我们并没有改变区间的值,而是改变的两个数之间的相对大小
对于树上差分:
父亲节点u = 其所有的子节点 + 他本身的差分数组
我们现在改变S到T边上所有点的值
我们对S的父亲节点减1,对T加1
//把s->t路径上所有点均加w,
chafen[t] += w;
chafen[s的父节点] -= w;
当计算每个点具体值时:
for(遍历与 u 相连的每一个子节点 v){num[u] += num[v];
}
num[u] += chafen[u];//加上差分数组
在本题中结合lca即可
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;const int maxn = 300050;
const int maxm = maxn << 1;
int N, M;
int a[maxn], t1, t2;
int head[maxn], cnt;struct Edge{int u, v, next;
}edge[maxm];inline void addedge(int u, int v){edge[++cnt].u = u;edge[cnt].v = v;edge[cnt].next = head[u];head[u] = cnt;
}int fa[maxn][31], dep[maxn];void dfs(int u, int faa){fa[u][0] = faa, dep[u] = dep[faa] + 1;for(int i = 1; i <= 30; i++){fa[u][i] = fa[ fa[u][i - 1] ][i - 1];}for(int i = head[u]; i ; i = edge[i].next){int v = edge[i].v;if(v == faa)continue;dfs(v, u);}
} inline int lca(int x, int y){if(dep[x] < dep[y])swap(x,y);for(int i = 30; i >= 0; i--){if(dep[ fa[x][i] ] >= dep[y]) x = fa[x][i];}if(x == y)return x;for(int i = 30; i >= 0; i--){if(fa[x][i] != fa[y][i]){x = fa[x][i], y = fa[y][i];}}return fa[x][0];
}int num[maxn];int answer(int u, int faa){for(int i = head[u]; i ; i = edge[i].next){int v = edge[i].v;if(v == faa)continue;answer(v, u);num[u] += num[v];}
}
int main(){cin>>N;for(int i = 1; i <= N; i++){cin>> a[i];}for(int i = 1; i < N; i++){cin>> t1>> t2;addedge(t1, t2);addedge(t2, t1);}dfs(1, 0);for(int i = 1; i <= N - 1; i++){int u = a[i], v = a[i + 1];int t = lca(u, v);num[ fa[t][0] ] -= 1;num[ t ] -= 1;num[ u ] += 1;num[ v ] += 1;}answer(1,0);for(int i = 2; i <= N; i++){num[a[i]]--;}for(int i = 1; i <= N; i++){cout<<num[i]<<endl;}
}
树链剖分
树链剖分就直接进行区间修改加一就行哈
代码:
这个代码我调了半个晚上,哭了哭了,终于调好了
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
inline int read(){int s=0,w=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();//s=(s<<3)+(s<<1)+(ch^48);return s*w;
}
const int maxn=1e6+9;
int a[maxn];
struct node{int u,v,next;
}edge[maxn];
int cnt=0;
int tot=0;
int n;
int head[maxn];
void add(int u,int v)
{edge[++cnt].v=v;edge[cnt].next=head[u];head[u]=cnt;
}
//---
int tr[maxn<<2],laz[maxn<<2];
inline void pushup(int rt)
{tr[rt]=tr[rt<<1]+tr[rt<<1|1];
}
inline void pushdown(int rt,int l,int r)
{int len=(r-l+1);laz[rt<<1]+=laz[rt];laz[rt<<1|1]+=laz[rt];tr[rt<<1]+=laz[rt]*(len-(len>>1));tr[rt<<1|1]+=laz[rt]*(len>>1);laz[rt]=0;
}
inline void build(int rt,int l,int r)
{if(l==r){tr[rt]=0;return ;}int mid=l+r>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);pushup(rt);
}
inline int query(int rt,int l,int r,int ip)
{if(l==ip&&r==ip)return tr[rt];if(laz[rt])pushdown(rt,l,r);int mid=l+r>>1;int ress=0;if(ip<=mid)ress+=query(rt<<1,l,mid,ip);if(ip>mid)ress+=query(rt<<1|1,mid+1,r,ip);return ress;
}
inline void update(int rt,int l,int r,int L,int R,int k)
{if(L<=l&&r<=R){int len=(r-l+1);laz[rt]+=k;tr[rt]+=k*len;}else {if(laz[rt])pushdown(rt,l,r);int mid=l+r>>1;if(L<=mid)update(rt<<1,l,mid,L,R,k);if(R>mid)update(rt<<1|1,mid+1,r,L,R,k);pushup(rt);}
}
//---
int fa[maxn],dep[maxn],siz[maxn],id[maxn],top[maxn],son[maxn];
inline int updrange(int x,int y,int k)
{while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])swap(x,y);update(1,1,n,id[top[x]],id[x],k);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);update(1,1,n,id[x],id[y],k);
}
inline void dfs1(int x,int f,int deep)
{dep[x]=deep;fa[x]=f;siz[x]=1;int maxson=-1;for(int i=head[x];i;i=edge[i].next){int v=edge[i].v;if(v==f)continue;dfs1(v,x,deep+1);siz[x]+=siz[v];if(siz[v]>maxson){son[x]=v;maxson=siz[v];}}
}
inline void dfs2(int x,int topf)
{id[x]=++tot;top[x]=topf;if(!son[x])return ;dfs2(son[x],topf);for(int i=head[x];i;i=edge[i].next){int v=edge[i].v;if(v==fa[x]||v==son[x])continue;dfs2(v,v);}
}
void print()
{for(int i=1;i<=n;i++){printf("%d\n",query(1,1,n,id[i]));//cout<<<<endl;}
// printf("----\n");
}
int main()
{cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<n;i++){int x,y;cin>>x>>y;add(x,y);add(y,x);}dfs1(a[n],0,1);dfs2(a[n],a[n]);build(1,1,n);updrange(a[1],a[1],1);//print();for(int i=1;i<n;i++){updrange(a[i],a[i+1],1);updrange(a[i],a[i],-1);// print();}updrange(a[n],a[n],-1);print();return 0;
}
P3258 [JLOI2014]松鼠的新家相关推荐
- 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 树上差分
缘起 [1]中我们学习了树上差分,并且a了一个裸的点差分. 现在继续树上差分~ 洛谷 P3258 [JLOI2014]松鼠的新家 分析 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房 ...
- P3258[JLOI2014]松鼠的新家(LCA 树上差分)
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- P3258 [JLOI2014] 松鼠的新家 题解
P3258 [JLOI2014] 松鼠的新家 题解 洛谷 P3258 题目 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有 nnn 个房间,并且有 nnn−1 根树枝连接,每个房间都可以相互到达,且 ...
- P3258 [JLOI2014]松鼠的新家(树上点查分)
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上. ...
- 洛谷 P3258 [JLOI2014]松鼠的新家
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上. ...
- 洛谷P3258 [JLOI2014]松鼠的新家
题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上. ...
- 洛谷 P3258 [JLOI2014]松鼠的新家(树链剖分)
题目要求熟练掌握树剖的概念,以及确定线段树的标号,题目应该不算难 这 n 个点之间,每两点之间都加 1 ,这样只有最后一个点和第一个点没有做多余的操作,题目还要求最后一次到达终点时不用再拿糖果,所以除 ...
- [Luogu 3258] JLOI2014 松鼠的新家
[Luogu 3258] JLOI2014 松鼠的新家 LCA + 树上差分. 我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分. qwq不讲了不讲了,贴代码. #i ...
最新文章
- B 站 Up 主自制秃头生成器,独秃头不如众秃头?
- fluent二维叶型仿真_ICEM划分嵌套网格之二维圆柱绕流
- mysql命令导入导出数据_mysql命令行导入和导出数据
- OA系统常见的审批流程
- 金蝶凭证序时簿在哪_来了!金蝶日常账务处理大全
- Java核心技术 卷1 多线程----线程安全的集合(4)
- C4-Squid-Purge
- 思科路由器RIP路由汇总
- Unity3D_(插件)小地图自刷新制作Minimap小地图
- Android业务组件化之Gradle和Sonatype Nexus搭建私有maven仓库
- 译:Datetime类型的扩展
- matlab2010b无法启动,MATLAB2010b simulink 启动警告问题
- 设计模式之责任链模式(Java实现)
- 反病毒工具-C32ASM
- 干货 | 在搜索引擎广告关键词生成上,算法可以做什么?
- DeFi新玩法丨一文教你玩转NFT碎片化协议Fractional
- React路由跳转时通过传参进行动态渲染的方法
- 新版Win10来了!丑哭了?
- 《Smallpdf》简单好用的线上PDF工具
- JavaScript之DOM和BOM
热门文章
- 你永远不知道女生裙子下面藏着什么
- shell查找命令大全
- datav本地部署 java,Spring Boot对Spring Data JPA的自动配置
- 电脑温度检测软件哪个好_实时检测Mac电脑的温度
- c语言求平衡因子,平衡二叉树(AVL树)的基本操作
- 全国计算机考试光盘,全国计算机一级模拟考试题(光盘).doc
- adonis.js mysql_Adonis.js——数据库基本操作
- fcn网络训练代码_另辟蹊径,中科院自动化所等首次用图卷积网络解决语义分割难题...
- html点击图片弹出大图特效代码,Jquery 点击图片在弹出层显示大图
- acwing2019. 拖拉机(最短路径)