Luogu P3258

题意就是对于一棵树,要求按照给出的顺序对每一个节点进行访问,记录每一个节点被经过的次数;特别地,我们认为只有从一个节点往外走才能被认为是经过一次。(最后一句话非常重要,仔细理解题意)

前置知识:树链剖分,差分。

最开始看到这道题我是打算使用树链剖分+线段树来做的。

但是我发现这个答案只需要每一个房间的糖果数……也就是说只需要区间修改+单点查询。

如果使用线段树的话,可能造成大量的空间浪费,而且常数也不小。

所以,我选择了使用树链剖分+差分进行统计。

由于差分写得比较少,本人卡了好一会。

大致思路如下:对于\(a[i-1]\)和\(a[i]\)两个节点,利用树链剖分求出两者之间的路径。

其实就是树剖求\(LCA\),每次比较两点的链头深度,深度大的往上跳,直至两点位于同一重链上。

把经过的每一个点权\(+1\),终点会被重复统计,所以每一次处理完毕都要让终点\(-1\)。

#include<cstdio>
#include<algorithm>
using namespace std;
struct data
{
int to,next;
}e[600005];
int head[300005],cnt,size[300005],fa[300005],d[300005],top[300005];
int a[300005],ans[3000005],id[300005],tim,wson[300005],n;
void add(int u,int v)
{
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void dfs1(int u,int f,int de)
{
size[u]=1;
fa[u]=f;
d[u]=de;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (v==f) continue;
dfs1(v,u,de+1);
size[u]+=size[v];
if (size[wson[u]]<size[v]) wson[u]=v;
}
}
void dfs2(int u,int t)
{
top[u]=t;
id[u]=++tim;
if (wson[u]) dfs2(wson[u],t);
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (v==fa[u]||v==wson[u]) continue;
dfs2(v,v);
}
}
void lca(int x,int y)
{
if (d[top[x]]<d[top[y]]) swap(x,y);
while (top[x]!=top[y])
{
if (d[top[x]]<d[top[y]]) swap(x,y);
ans[id[top[x]]]+=1;ans[id[x]+1]-=1;
x=fa[top[x]];
}
if (d[x]<d[y]) swap(x,y);
ans[id[y]]+=1;ans[id[x]+1]-=1;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1(1,0,1);
dfs2(1,1);
for (int i=2;i<=n;i++)
{
lca(a[i],a[i-1]);
ans[id[a[i]]]--;
ans[id[a[i]]+1]++;
//注意dfs序和原编号的映射关系
}
for (int i=1;i<=n;i++)
ans[i]+=ans[i-1];//用差分数组求出答案数组
for (int i=1;i<=n;i++) printf("%d\n",ans[id[i]]);
return 0;
}

最新文章

  1. 在开发中到底要不要用var?
  2. Windows Server 2008下asp+access无法登陆问题总结
  3. PHP中phar包的使用
  4. MVVM架构~knockoutjs系列之验证信息自定义输出
  5. JS - To my gril
  6. MySQL数据库还原:路径必须用正斜杠?
  7. 《C和指针》章节后编程练习解答参考——6.3
  8. 【Java】WEB-INF目录与META-INF目录的作用
  9. html5 - drag 拖拽
  10. Java 虚拟机概述
  11. MySQL面试题之为什么要为innodb表设置自增列做主键?
  12. mac下更改Jupyter notebook工作目录
  13. 18职责链模式CoR
  14. Hibernate.编写xml文件无自动提示信息
  15. ChromeDriver与Chrome版本对应关系
  16. 【基础】selenium中元素定位的常用方法(三)
  17. HDU 1159:Common Subsequence(LCS模板)
  18. VS版本号定义、规则和相关的Visual Studio插件
  19. .NET 开源Protobuf-net从入门到精通
  20. 将一个byte[]数组根据大小拆分为若干小byte[]数组方法

热门文章

  1. C语言中【变量】的存储类型共有4种类型
  2. 洛谷 P1966 火柴排队 题解
  3. 创建一个简单tcp服务器需要的流程
  4. 统计单词Java
  5. AspNetCore3.0 和 JWT
  6. RabbitMQ面试问答(子文章)(持续更新)
  7. namenode 性能优化 RPC队列拆分
  8. [提权]mysql中的UDF提权
  9. thymeleaf错误解决办法
  10. TCP粘包拆包问题分析及应对方案