题目链接

题目大意:

有一棵N个结点树和N头奶牛,一开始所有奶牛都在一号结点,奶牛们将按从编号1到编号N的顺序依次前往自己的目的地,求每头奶牛在去往自己目的地的途中将会经过多少已经有奶牛的结点。

题解:

可以发现,每一头奶牛到达目的地后,都只会对还未到达目的地的奶牛中,目的地在它目的地子树中的奶牛的答案产生贡献。

比如说在下面这棵树中,一头奶牛到达了图中深色结点,那么在还未到达目的地的奶牛中,只有目的地在深色结点子树中的奶牛才会由深色结点对答案产生贡献。

所以,我们可以在每头奶牛到达目的地后,将其目的地所在结点的子树中每一个结点的权值都加上一,询问时输出该奶牛目的地所在结点的权值即可。

由于每一次的修改操作都是在一棵子树内进行的,所以考虑用dfs序给结点编号(因为每棵子树中结点的dfs序都一定是连续的一段),再用线段树进行维护就好。

代码:

#include<iostream>
#include<cstdio>
using namespace std;
struct edge
{
int last;
int end;
}e[200005];
int ne=0,idx=0,dfn[100005],note[100005],size[100005],tree[400005],lazy[400005];
void make_edge(int u,int v)
{
ne++;
e[ne].last=note[u];
e[ne].end=v;
note[u]=ne;
}
void dfs(int x,int fx)
{
dfn[x]=++idx;//用dfs序给结点编号
size[x]=1;
for(int i=note[x];i;i=e[i].last)
if(e[i].end!=fx)
{
dfs(e[i].end,x);//继续dfs
//计算每个结点的子树大小,用于计算此结点的子树中最大的dfs序是多少,便于操作
size[x]+=size[e[i].end];
}
}
//线段树板子
void add_node(int p,int l,int r,int k)
{
tree[p]+=(r-l+1)*k;
lazy[p]+=k;
}
void clean_lazy(int p,int l,int r)
{
int mid=(l+r)>>1;
add_node((p<<1),l,mid,lazy[p]);
add_node((p<<1)+1,mid+1,r,lazy[p]);
lazy[p]=0;
}
void add(int p,int l,int r,int x,int y)
{
if(x>y) return;
if(l==x&&r==y)
{
add_node(p,l,r,1);
return;
}
clean_lazy(p,l,r);
int mid=(l+r)>>1;
if(y<=mid) add((p<<1),l,mid,x,y);
else if(x>mid) add((p<<1)+1,mid+1,r,x,y);
else add((p<<1),l,mid,x,mid),add((p<<1)+1,mid+1,r,mid+1,y);
}
int ask(int p,int l,int r,int x)
{
if(l==r) return tree[p];
clean_lazy(p,l,r);
int mid=(l+r)>>1;
if(x<=mid) return ask((p<<1),l,mid,x);
return ask((p<<1)+1,mid+1,r,x);
}
int main()
{
int n=0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u=0,v=0;
scanf("%d%d",&u,&v);
make_edge(u,v);
make_edge(v,u);
}
dfs(1,0);
for(int i=1;i<=n;i++)
{
int x=0;
scanf("%d",&x);
printf("%d\n",ask(1,1,n,dfn[x]));//直接输出目的地所在的权值
add(1,1,n,dfn[x]+1,dfn[x]+size[x]-1);//给当前目的地所在结点的子树中所有结点的权值都加1
}
return 0;
}

最新文章

  1. linux下使用fork,exec,waitpid模拟system函数
  2. 编码Q&amp;A
  3. Oracle 创建主键自增表
  4. 代码重构-3 用Tuple代替 out与ref
  5. (转)深入理解javascript的function
  6. LA 2995 Image Is Everything 立方体成像 World Final 2004
  7. Android 查看内存
  8. 1 Yoga3 系统装机总结.
  9. JSP基础语法--跳转指令 jsp:forward page
  10. Linux 下 git的使用
  11. Professional C# 6 and .NET Core 1.0 - 40 ASP.NET Core
  12. javaWeb学习总结(3)- Servlet基础
  13. C#语法糖演进-C#语言和.NET Framework平台介绍
  14. 命令行备忘录 cli-memo
  15. Bitmap Byte[] 互转
  16. Python3 ElementTree.tostring()导致标签前辍变为ns0/ns1处理
  17. php苹果内购订单验证
  18. 大话C#中能使用foreach的集合的实现
  19. Angular入门笔记
  20. c++中c_str()用法

热门文章

  1. learn git(远程仓库github)
  2. Git(1) - Git、Github和Gitlab简介
  3. mybatis多条件多值批量更新
  4. cas的基础配置
  5. P7736-[NOI2021]路径交点【LGV引理】
  6. P3507-[POI2010]GRA-The Minima Game【dp,博弈论】
  7. AtCoder Beginner Contest 221 A~E题解
  8. Java实现四大基本排序算法和二分查找
  9. 前端从web服务器或者CDN下载资源
  10. 数据库MySQL主从-GTID