题目描述

小c同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。天天爱跑步是一个养成类游戏,需要 玩家每天按时上线,完成打卡任务。

这个游戏的地图可以看作一一棵包含 N个结点和N-1 条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从1到N的连续正整数。

现在有个玩家,第个玩家的 起点为Si ,终点为Ti 。每天打卡任务开始时,所有玩家在第0秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务。 (由于地图是一棵树, 所以 每个人的路径是唯一的)

小C想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点的观察员会选 择在第Wj秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第Wj秒也正好到达了结点J 。 小C想知道 每个观察员会观察到多少人?

注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一 段时 间后再被观察员观察到。 即对于把结点J作为终点的玩家: 若他在第Wj秒重到达终点,则在结点J的观察员不能观察 到该玩家;若他正好在第Wj秒到达终点,则在结点的观察员可以观察到这个玩家。

输入格式

第一行有两个整数N和M 。其中N代表树的结点数量, 同时也是观察员的数量, M代表玩家的数量。

接下来n-1 行每行两个整数U和V ,表示结点U 到结点V 有一条边。

接下来一行N 个整数,其中第个整数为Wj , 表示结点出现观察员的时间。

接下来 M行,每行两个整数Si和Ti,表示一个玩家的起点和终点。

对于所有的数据,保证 。1<=Si,Ti<=N,0<=Wj<=N

输出格式

输出1行N 个整数,第j个整数表示结点j的观察员可以观察到多少人。

解题思路:

方法一:线段树+树链剖分

首先,我们考虑什么样的玩家可以被看到,那么就是说什么时候玩家到某个节点。

设玩家初始时的位置深度为d。

大概是这样的,如果玩家在向上走时,会在0时刻走到路径上d深度的点,在1时刻走到d-1深度的点,2时刻走到d-2是深度的点。

那么在向上走的过程中,所经过点上的观察员只要使等式(w+deep)=d成立,就能看见玩家。

同样的在玩家向下走的时候也有类似的结论,就是只要玩家的(d-2*路径上lca的deep)=(w-deep)就能看见。

那么我们开线段树存就好了。

对于每个深度开两棵线段树分别记录向下走的和向上走的某个节点观察的值,也就是说在每一个玩家的d上的线段树对于每个玩家经历的点上统一+1。

也就是说树链上+1,这样只要单点查询就可以了。

树链上+1,使用树链剖分就好了^_^

线段树占很大空间动态开点就好了

还有对于一些深度较浅的点我们发现最终的向下行走的索引可能为负,所以对于向下走的线段树索引统一加上3e5

大概就是这样了^_^

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=(int)(3e5);
const int T=(int)();
struct pnt{
int w;
int hd;
int dp;
int fa;
int wgt;
int mxs;
int ind;
int top;
}p[N];
struct ent{
int twd;
int lst;
}e[N*];
struct sgt{
int ls;
int rs;
int vls;
}tr[T];
int cnt;
int siz;
int dnt;
int n,m;
int rtu[N*],rtd[N*];
int sta[N],fin[N];
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
}
void Tr_pushdown(int spc)
{
if(tr[spc].ls)
tr[tr[spc].ls].vls+=tr[spc].vls;
if(tr[spc].rs)
tr[tr[spc].rs].vls+=tr[spc].vls;
tr[spc].vls=;
}
void Tr_build(int &spc,int l,int r,int plc)
{
if(!spc)
spc=++siz;
if(l==r)
return ;
int mid=(l+r)/;
if(plc<=mid)
Tr_build(tr[spc].ls,l,mid,plc);
else
Tr_build(tr[spc].rs,mid+,r,plc);
} void Tr_add(int ll,int rr,int l,int r,int spc,int v)
{
if(!spc)
return ;
if(ll>r||l>rr)
return ;
if(ll<=l&&rr>=r)
{
tr[spc].vls+=v;
return ;
}
int mid=(l+r)/;
Tr_add(ll,rr,l,mid,tr[spc].ls,v);
Tr_add(ll,rr,mid+,r,tr[spc].rs,v);
return ;
}
int Tr_val(int plc,int spc,int l,int r)
{
if(!spc)
return ;
if(l==r)
return tr[spc].vls;
Tr_pushdown(spc);
int mid=(l+r)/;
if(plc<=mid)
return Tr_val(plc,tr[spc].ls,l,mid);
else
return Tr_val(plc,tr[spc].rs,mid+,r);
}
void Basic_dfs(int x,int f)
{
p[x].fa=f;
p[x].dp=p[f].dp+;
p[x].wgt=;
int maxs=;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(maxs<p[to].wgt)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
}
void Build_dfs(int x,int tp)
{
if(!x)
return ;
p[x].ind=++dnt;
p[x].top=tp;
Tr_build(rtu[p[x].dp+p[x].w],,n,dnt);
Tr_build(rtd[p[x].w-p[x].dp+N],,n,dnt);
Build_dfs(p[x].mxs,tp);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].ind)
continue;
Build_dfs(to,to);
}
}
int LCA(int x,int y)
{
while(p[x].top!=p[y].top)
{
if(p[p[x].top].dp<p[p[y].top].dp)
swap(x,y);
x=p[p[x].top].fa;
}
if(p[x].dp>p[y].dp)
swap(x,y);
return x;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
ade(x,y);
ade(y,x);
}
for(int i=;i<=n;i++)
scanf("%d",&p[i].w);
for(int i=;i<=m;i++)
scanf("%d%d",&sta[i],&fin[i]);
Basic_dfs(,);
Build_dfs(,);
for(int i=;i<=m;i++)
{
int f=LCA(sta[i],fin[i]);
int x=sta[i];
int rt=p[sta[i]].dp;
while(p[x].top!=p[f].top)
{
Tr_add(p[p[x].top].ind,p[x].ind,,n,rtu[rt],);
x=p[p[x].top].fa;
}
Tr_add(p[f].ind,p[x].ind,,n,rtu[rt],);
Tr_add(p[f].ind,p[f].ind,,n,rtu[rt],-);
x=fin[i];
rt=N+p[sta[i]].dp-*p[f].dp;
while(p[x].top!=p[f].top)
{
Tr_add(p[p[x].top].ind,p[x].ind,,n,rtd[rt],);
x=p[p[x].top].fa;
}
Tr_add(p[f].ind,p[x].ind,,n,rtd[rt],);
}
for(int i=;i<=n;i++)
{
int dowsid=Tr_val(p[i].ind,rtd[N+p[i].w-p[i].dp],,n);
int upsid=Tr_val(p[i].ind,rtu[p[i].dp+p[i].w],,n);
printf("%d ",dowsid+upsid);
}
return ;
}

NOIP2016 天天爱跑步(线段树/桶)的更多相关文章

  1. [NOIp2016]天天爱跑步 线段树合并

    [NOIp2016]天天爱跑步 LG传送门 作为一道被毒瘤出题人们玩坏了的NOIp经典题,我们先不看毒瘤的"动态爱跑步"和"天天爱仙人掌",回归一下本来的味道. ...

  2. NOIP2016 天天爱跑步 线段树合并_桶_思维题

    竟然独自想出来了,好开心 Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r&q ...

  3. 2018.08.09 bzoj4719: [Noip2016]天天爱跑步(树链剖分)

    传送门 话说开始上文化课之后写题时间好少啊. 这道题将一个人的跑步路线拆成s->lca,lca->t,然后对于第一段上坡路径要经过的点,当前这个人能对它产生贡献当且仅当dep[s]-dep ...

  4. [Noip2016]天天爱跑步 LCA+DFS

    [Noip2016]天天爱跑步 Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.?天天爱跑步?是一个养成类游戏,需要玩家每天按时上线,完成打卡任 ...

  5. 【LG1600】[NOIP2016]天天爱跑步

    [LG1600][NOIP2016]天天爱跑步 题面 洛谷 题解 考虑一条路径\(S\rightarrow T\)是如何给一个观测点\(x\)造成贡献的, 一种是从\(x\)的子树内出来,另外一种是从 ...

  6. [NOIP2016]天天爱跑步(树上差分+线段树合并)

    将每个人跑步的路径拆分成x->lca,lca->y两条路径分别考虑: 对于在点i的观察点,这个人(s->t)能被观察到的充要条件为: 1.直向上的路径:w[i]=dep[s]-dep ...

  7. 【bzoj4719】[Noip2016]天天爱跑步 权值线段树合并

    题目描述 给出一棵n个点的树,以及m次操作,每次操作从起点向终点以每秒一条边的速度移动(初始时刻为0),最后对于每个点询问有多少次操作在经过该点的时刻为某值. 输入 第一行有两个整数N和M .其中N代 ...

  8. BZOJ4719 NOIP2016天天爱跑步(线段树合并)

    线段树合并的话这个noip最难题就是个裸题了. 注意merge最后return x,以及如果需要区间查询的话这里还需要up,无数次死于这里. #include<iostream> #inc ...

  9. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...

随机推荐

  1. springMVC --全局异常处理(两种方式)

    首先看springMVC的配置文件: <!-- 全局异常配置 start --> <bean id="exceptionResolver" class=" ...

  2. 小白学开发(iOS)OC_ 经常使用结构体(2015-08-14)

    // //  main.m //  经常使用结构体 // //  Created by admin on 15/8/13. //  Copyright (c) 2015年 admin. All rig ...

  3. 逆波兰表达式解数学运算(c#)

    逆波兰表达式解数学运算 感谢作者 http://blog.csdn.net/liuyuxusuixiang/article/details/25289715 public class TCalcula ...

  4. Linux 内核源码(kernel source)

    查看内核的发行版:uname -r(--kernel-release) $ uname -r 4.4.0-78-generic 内核源码所在的位置:/usr/src $ cd /usr/src $ l ...

  5. CORS with Spring MVC--转

    原文地址:http://dontpanic.42.nl/2015/04/cors-with-spring-mvc.html CORS with Spring MVC   In this blog po ...

  6. Cisco交换机端口安全

    Cisco交换机端口安全       通过端口设置,可以限制允许访问交换机上某个端口的MAC地址以及IP(可选)来实现严格控制对该端口的输入,最终确保网络接入安全.配置网络安全时应该注意如下问题: 1 ...

  7. Chromium Graphics : GPU Accelerated Compositing in Chrome

    GPU Accelerated Compositing in Chrome Tom Wiltzius, Vangelis Kokkevis & the Chrome Graphics team ...

  8. angular-cli6使用ng serve --o 控制台报错Invalid Host Header

    angular-cli6使用ng serve --o 运行创建的项目,能正常访问,但是控制台一直在报错,点击报错能看到是因为webpack的webpack-dev-server里报的错, 看到网上介绍 ...

  9. gcc---C/C++ 编译器

    gcc命令使用GNU推出的基于C/C++的编译器,是开放源代码领域应用最广泛的编译器,具有功能强大,编译代码支持性能优化等特点.现在很多程序员都应用GCC,怎样才能更好的应用GCC.目前,GCC可以用 ...

  10. redis练习手册<二>快速入门

    Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的Web应用程序的完美解决方案. Redis从它的许多竞争继承来的三个主要特点: Redis数据库完全在内存中,使用磁盘仅用 ...