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

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

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

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

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

输入输出格式
输入格式:
第一行有两个整数nn和mm 。其中nn代表树的结点数量, 同时也是观察员的数量, mm代表玩家的数量。

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

接下来一行 nn个整数,其中第jj个整数为W_jW
j
​ , 表示结点jj出现观察员的时间。

接下来 mm行,每行两个整数S_iS
i
​ ,和T_iT
i
​ ,表示一个玩家的起点和终点。

对于所有的数据,保证1\leq S_i,T_i\leq n, 0\leq W_j\leq n1≤S
i
​ ,T
i
​ ≤n,0≤W
j
​ ≤n 。

输出格式:
输出1行 nn个整数,第jj个整数表示结点jj的观察员可以观察到多少人。

输入输出样例
输入样例#1:
6 3
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6
输出样例#1:
2 0 0 1 1 1
输入样例#2:
5 3
1 2
2 3
2 4
1 5
0 1 0 3 0
3 1
1 4
5 5
输出样例#2:
1 2 1 0 1

题解:号称提高组最难一题,其实难度还行

考虑把一个人的路径拆成起点到lca和lca到终点两段,差分一下用线段树维护

具体的操作是对起点插入deep起点,终点插入2*deep[lca]-deep起点,相当于把起点沿lca翻上去。

然后线段树合并一波就搞定了

查询的是每个点deep+wj和deep-wj距离的点有几个

其实线段树合并是大材小用了,如果对每个点查询li-ri时间之间有多少人经过显然才更妙

代码如下:

#include<bits/stdc++.h>
#define lson tr[now].l
#define rson tr[now].r
using namespace std; struct tree
{
int l,r,sum;
} tr[]; vector<int> g[];
vector<int> op1[],op2[];
int n,m,ans[],q[],rt[],deep[],fa[][],cnt;
int N=; int dfs(int now,int f,int dep)
{
deep[now]=dep;
fa[now][]=f;
rt[now]=now;
++cnt;
for(int i=; i<=; i++)
{
fa[now][i]=fa[fa[now][i-]][i-];
}
for(int i=; i<g[now].size(); i++)
{
if(g[now][i]==f) continue;
dfs(g[now][i],now,dep+);
}
} int lca(int x,int y)
{
if(deep[x]<deep[y]) swap(x,y);
for(int i=; i>=; i--)
{
if(deep[fa[x][i]]>=deep[y]) x=fa[x][i];
}
if(x==y) return x;
for(int i=; i>=; i--)
{
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
}
return fa[x][];
} int push_up(int now)
{
tr[now].sum=tr[lson].sum+tr[rson].sum;
} int insert(int &now,int l,int r,int pos,int val)
{
if(!now) now=++cnt;
if(l==r)
{
tr[now].sum+=val;
return ;
}
int mid=(l+r)>>;
if(pos<=mid)
{
insert(lson,l,mid,pos,val);
}
else
{
insert(rson,mid+,r,pos,val);
}
push_up(now);
} int query(int now,int l,int r,int pos)
{
if(l==r) return tr[now].sum;
int mid=(l+r)>>;
if(pos<=mid) return query(lson,l,mid,pos);
else return query(rson,mid+,r,pos);
} int merge(int a,int b,int l,int r)
{
if(!b) return a;
if(!a) return b;
if(l==r)
{
tr[a].sum+=tr[b].sum;
return a;
}
int mid=(l+r)>>;
tr[a].l=merge(tr[a].l,tr[b].l,l,mid);
tr[a].r=merge(tr[a].r,tr[b].r,mid+,r);
push_up(a);
return a;
} int solve(int now,int f)
{
for(int i=; i<op1[now].size(); i++)
{
insert(rt[now],,N,op1[now][i],);
}
for(int i=; i<op2[now].size(); i++)
{
insert(rt[now],,N,op2[now][i],-);
}
for(int i=; i<g[now].size(); i++)
{
if(g[now][i]==f) continue;
solve(g[now][i],now);
merge(rt[now],rt[g[now][i]],,N);
}
if(deep[now]+n-q[now]>=) ans[now]+=query(rt[now],,N,deep[now]+n-q[now]);
if(deep[now]+n+q[now]<=N&&q[now]!=) ans[now]+=query(rt[now],,N,deep[now]+n+q[now]);
} int main()
{
int from,to;
scanf("%d%d",&n,&m);
for(int i=; i<n; i++)
{
scanf("%d%d",&from,&to);
g[from].push_back(to);
g[to].push_back(from);
}
for(int i=; i<=n; i++) scanf("%d",&q[i]);
dfs(,,);
for(int i=; i<=m; i++)
{
scanf("%d%d",&from,&to);
int anc=lca(from,to);
op1[from].push_back(deep[from]+n);
op1[to].push_back(n-(deep[from]-deep[anc])+deep[anc]);
op2[anc].push_back(deep[from]+n);
op2[fa[anc][]].push_back(n-(deep[from]-deep[anc])+deep[anc]);
}
solve(,);
for(int i=;i<=n;i++)
{
printf("%d ",ans[i]);
}
}

洛谷P1600 天天爱跑步(线段树合并)的更多相关文章

  1. 洛谷 P1600 天天爱跑步

    https://www.luogu.org/problemnew/show/P1600 (仅做记录) 自己的假方法: 每一次跑从a到b:设l=lca(a,b)对于以下产生贡献: a到l的链上所有的点( ...

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

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

  3. 洛谷P3899 [湖南集训]谈笑风生(线段树合并)

    题意 题目链接 Sol 线段树合并板子题,目前我看到两种写法,分别是这样的. 前一种每次需要新建一个节点,空间是\(O(4nlogn)\) 后者不需要新建,空间是\(O(nlogn)\)(面向数据算空 ...

  4. 洛谷P3521 [POI2011]ROT-Tree Rotation [线段树合并]

    题目传送门 Tree Rotation 题目描述 Byteasar the gardener is growing a rare tree called Rotatus Informatikus. I ...

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

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

  6. 洛谷P1600 天天爱跑步

    天天放毒... 首先介绍一个树上差分. 每次进入的时候记录贡献,跟出来的时候的差值就是子树贡献. 然后就可以做了. 发现考虑每个人的贡献有困难. 于是考虑每个观察员的答案. 把路径拆成两条,以lca分 ...

  7. 洛谷P1600 天天爱跑步——树上差分

    题目:https://www.luogu.org/problemnew/show/P1600 看博客:https://blog.csdn.net/clove_unique/article/detail ...

  8. 洛谷 P1600 天天爱跑步(LCA+乱搞)

    传送门 我们把每一条路径拆成$u->lca$和$lca->v$的路径 先考虑$u->lca$,如果这条路径会对路径上的某一个点产生贡献,那么满足$dep[u]-dep[x]=w[x] ...

  9. 洛谷P1600 天天爱跑步——题解

    题目传送 首先要考虑入手点.先考虑一个一个玩家处理,显然不加优化的话,时间复杂度是O(n)的.发现对于玩家路径上的点都有一个观察员,一个都不能忽视,看起来是很难优化了.在做题时,发现一个思路很难想,就 ...

随机推荐

  1. session第二篇

    二 A.application对象 1.application对象实现了用户间数据的共享,可存放全局变量. 2.application对象开始于服务器的启动,终止于服务器的关闭. 3.在用户的前后连接 ...

  2. java mysql大数据量批量插入与流式读取分析

    总结下这周帮助客户解决报表生成操作的mysql 驱动的使用上的一些问题,与解决方案.由于生成报表逻辑要从数据库读取大量数据并在内存中加工处理后在 生成大量的汇总数据然后写入到数据库.基本流程是 读取- ...

  3. 列表中语句 python

    找到两个列表中相同元素: list1 = [1,2,3,4,5] list2 = [4,5,6,7,8] print ([l for l in list1 if l in list2]) 输出: [4 ...

  4. ubuntu下搭建testlink

    环境配置: 1. 安装mysql 教程网上找 2. 安装apache sudo apt-get install apache2 重启apache服务 sudo /etc/init.d/apache2 ...

  5. switch_to_frame,切换frame框架

    页面包含frame/iframe标签,需要先切换到该frame标签,再去定位属于这个frame的元素.   如果要再去定位其他frame的元素,需要回到该frame的上级,定位到要选择的frame,不 ...

  6. Hibernate一级缓存(补)

    ------------------siwuxie095                                 什么是缓存         缓存是介于应用程序和永久性数据存储源(如:硬盘上的 ...

  7. iOS9 UIWindow rootViewController

    在iOS9中App被其他应用唤起的时候Crash,正常启动或者调试模式都不会Crash. 通过XCode - Window -Device,查看设备的log,如下 Assertion failure ...

  8. 设置 svn 与 web线上同步

    默认你已经配置好了svn服务 1.假设我们的线上网站目录为:/data/www/xxx 2.假设svn的仓库目录为:/data/svn/repo 一.checkout一份svn到线上网站目录 svn ...

  9. ef linq 访问视图返回结果重复

    根据检测到的语句查询和linq查询出来的结果不一致,linq查询出重复的数据,原因不明,已改用ef直接查询视图,也许以后某一天突然就解决了,先mark下.

  10. PM2使用及介绍

    pm2 是一个带有负载均衡功能的Node应用的进程管理器.当你要把你的独立代码利用全部的服务器上的所有CPU,并保证进程永远都活着,0秒的重载, PM2是完美的.它非常适合IaaS结构,但不要把它用于 ...