问题 G: 天天爱跑步
时间限制: 2 Sec 内存限制: 512 MB
提交: 24 解决: 20
[提交][状态][讨论版]
题目描述
小C同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。《天天爱跑步》是一个养成类游戏,需要玩家每天按时上线,完成打卡任务。

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

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

小C想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点的观察员会选择在第Wj秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第Wj秒也理到达了结点J  。 小C想知道每个观察员会观察到多少人?注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一 段时间后再被观察员观察到。 即对于把结点J作为终点的玩家: 若他在第Wj秒重到达终点,则在结点J的观察员不能观察到该玩家;若他正好在第Wj秒到达终点,则在结点的观察员可以观察到这个玩家。

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

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

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

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

对于所有的数据,保证1≤Si,Ti≤n,0≤ Wj ≤n。

输出
输出1行n个整数,第j个整数表示结点j的观察员可以观察到多少人。
样例输入
6 3
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6
样例输出
2 0 0 1 1 1

很显然要用到LCA,但正解比LCA多很多。
一条路该分成两段,起点x到LCA,LCA到终点y。这里就要分别考虑了。对于第一段,对于其路径上的点i,t[i]==dep[x]-dep[i]时,就是dep[x]==t[i]+dep[i]。所以对于起点,就看对于点i有多少人起步于t[i]+dep[i]就好了。 那么对于第二段,len-(dep[y]-dep[i])==t[i],就是t[i]-dep[i]==len-depy,以同样的方式统计就行了。
这只是主体思路,离实现还差很远。因为同一深度不同路径会对答案产生影响,所以可以再来一发深搜。这样判断就变得较容易了。 可以开两个桶记录先前所述的第一段和第二段对答案的贡献,但之前的会产生影响,可以这样考虑,记录搜自己和子节点之前的值,用搜完的之后的值减去他,就是自己子树要过自己的数量了。。。而为了消除LCA对答案的影响,回溯回来时,要分别把以他为LCA的起点和终点的点在两个桶中分别减减
在这里搜答案时,我学(zhao)习(chao)神犇ljm的做法,把每个点向他所能对应的答案练了一条边。方便在dfs时查找答案,或是在回溯时减去。。

#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#define N 300000
using namespace std;
int read()
{int sum=0,f=1;char x=getchar();while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}while(x>='0'&&x<='9'){sum=(sum<<1)+(sum<<3)+x-'0';x=getchar();}return sum*f;
}
int n,m,adj[N],f[N],vis[N],dep[N],anc[N],ans[N];
int tim[N],A[N],sum[N],up[N*2],down[N*2];
int e,e1,e2,e3,e4;
int adj1[N*2],adj2[N*2],adj3[N*2],head[N];
struct Q{int v,next,id;}q[N*2];
struct road{int v,next;}lu[N*2],lu1[N*2],lu2[N*2],lu3[N*2];
void add(int u,int v){lu[++e].v=v;lu[e].next=adj[u];adj[u]=e;}
void add1(int u,int v){lu1[++e1].v=v;lu1[e1].next=adj1[u];adj1[u]=e1;}
void add2(int u,int v){lu2[++e2].v=v;lu2[e2].next=adj2[u];adj2[u]=e2;}
void add3(int u,int v){lu3[++e3].v=v;lu3[e3].next=adj3[u];adj3[u]=e3;}
void add_q(int u,int v,int id){q[e4].v=v;q[e4].id=id;q[e4].next=head[u];head[u]=e4++;}
int find(int x){return f[x]==x? x:f[x]=find(f[x]);}
void hb(int x,int y){int fx=find(x),fy=find(y);if(fx!=fy)f[fx]=fy;}
void dfs1(int x,int fa)
{dep[x]=dep[fa]+1;anc[x]=x;vis[x]=1;for(int i=adj[x];i;i=lu[i].next){int to=lu[i].v;if(vis[to])continue;dfs1(to,x);hb(x,to);anc[find(x)]=x;}for(int i=head[x];i!=-1;i=q[i].next){int to=q[i].v;if(vis[to])ans[q[i].id]=anc[find(to)];}
}
void dfs2(int x,int y)
{int t1=up[dep[x]+tim[x]],t2=down[dep[x]-tim[x]+N];up[dep[x]]+=A[x];for(int i=adj1[x];i;i=lu1[i].next)++down[lu1[i].v+N];for(int i=adj[x];i;i=lu[i].next)if(lu[i].v!=y)dfs2(lu[i].v,x);sum[x]=up[dep[x]+tim[x]]+down[dep[x]-tim[x]+N]-t1-t2;for(int i=adj2[x];i;i=lu2[i].next){int to=lu2[i].v;up[to]--;if(to==dep[x]+tim[x])sum[x]--;}for(int i=adj3[x];i;i=lu3[i].next)down[lu3[i].v+N]--;
}
int main()
{
//  freopen("runninga.in","r",stdin);
//  freopen("runninga.out","w",stdout);int __size__=64<<20; char *__p__=(char*)malloc(__size__)+__size__;  __asm__("movl %0, %%esp\n"::"r"(__p__));  n=read();m=read();int x,y,a,b;memset(head,-1,sizeof(head));for(int i=1;i<=n;i++)f[i]=i;for(int i=1;i<n;i++)x=read(),y=read(),add(x,y),add(y,x);for(int i=1;i<=n;i++)tim[i]=read();for(int i=0;i<m;i++)x=read(),y=read(),add_q(x,y,i),add_q(y,x,i);dfs1(1,0);for(int i=0;i<m;i++){x=q[i<<1].v,y=q[i<<1|1].v;a=dep[x]+dep[y]-dep[ans[i]]*2;b=dep[x]-a;++A[y];add1(x,b);add2(ans[i],dep[y]);add3(ans[i],b);}dfs2(1,0);for(int i=1;i<=n;i++)printf("%d ",sum[i]);
}

LCA 天天爱跑步相关推荐

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

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

  2. 【洛谷】1600:天天爱跑步【LCA】【开桶】【容斥】【推式子】

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

  3. BZOJ 4719--天天爱跑步(LCA差分)

    4719: [Noip2016]天天爱跑步 Time Limit: 40 Sec  Memory Limit: 512 MB Submit: 1464  Solved: 490 [Submit][St ...

  4. [luogu]P1600 天天爱跑步[LCA]

    [luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...

  5. [noip2016]天天爱跑步(主席树+lca)

    恩..在百度的第一页翻了翻,没有用主席树做的,于是打算水一篇blog: 天天爱跑步 首先有一个解题的关键: 将玩家的向上和向下分成两部分: 先定义几个变量,s是起点,t是终点,wi是每个观察员出现的时 ...

  6. [NOIP2016]天天爱跑步(lca+乱搞)

    2557. [NOIP2016]天天爱跑步 时间限制:2 s   内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑 ...

  7. NOIP2016天天爱跑步

    NOIP2016天天爱跑步 这题一看显然lca+树上差分,但是因为有w的限制不能直接加,所以考虑权值线段树合并, 每个选手的起点终点对于不同的节点的影响是不同的,这就非常麻烦了,但是可以发现无论如何他 ...

  8. Noip2016day1 天天爱跑步running

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

  9. P1600 天天爱跑步

    P1600 天天爱跑步 题目描述 详见:P1600 天天爱跑步 Solution 树上差分+LCA. Code #include<bits/stdc++.h> using namespac ...

最新文章

  1. Spark的基础应用
  2. C语言题解:用二分法思想求解10个元素中某个元素的下标(包含函数方法)
  3. 差分 c语言,c语言 bmp位图差分
  4. iOS无法引入头文件
  5. 合并a[0..mid]和a[mid+1,n-1],其中这两个数组分别有序
  6. linux 下的 initrd ramdisk
  7. git的使用学习(三)时光机穿梭
  8. AWS上的应用程序自动扩展–选项及其对性能的影响
  9. python发送excel文件_Python操作Excel, 开发和调用接口,发送邮件
  10. CentOS学习笔记 - 7. jekins安装 1
  11. cent mysql 配置,centos下MySQL安装配置
  12. 【算法模板】链表篇—(附牛客习题)
  13. Unity 文字转语音
  14. 设计和实现一款轻量级的爬虫框架
  15. mybati-plus自定义sql异常Invalid bound statement (not found)封装的sql查询正常
  16. CodeCademy | Python | 6. Pyglatin
  17. linux怎么安装网卡驱动固件,linux下安装网卡驱动的方法步骤
  18. python如何让用户输入_Python如何让用户输入
  19. 斐讯dns服务器未响应,p.to手机登录界面
  20. 上海迪士尼将推出虎年新春全新体验

热门文章

  1. c语言花卉销售与管理系统,网上花卉销售和管理系统毕业设计论文.doc
  2. 我怎么就被一张照片出卖了?可怕!
  3. 这可能是最完整的进藏攻略
  4. 有效 360 度反馈系统的关键
  5. j3455跑mysql_基于J3455搭建NAS
  6. 计算机控制室防火危险级为,8.2 空气调节 - 【已作废】火力发电厂与变电站设计防火规范 GB50229-2006 - 消防规范大全 - 消防资源网!...
  7. 双宾语与复合宾语,分词状语与独立主格状语
  8. How Broswer Work
  9. Mac安装ps软件,提示Error解决方法
  10. 禾川Q0 PLC ModbusRTU通讯