#261. 【NOIP2016】天天爱跑步

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

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

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

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

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

输入格式

从标准输入读入数据。

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

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

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

接下来 mm 行,每行两个整数 SiSi 和 TiTi,表示一个玩家的起点和终点。

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

输出格式

输出到标准输出。

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

样例一

input

6 3
2 3
1 2
1 4
4 5
4 6
0 2 5 1 2 3
1 5
1 3
2 6

output

2 0 0 1 1 1

explanation

对于 11 号点,W1=0W1=0,故只有起点为 11 号点的玩家才会被观察到,所以玩家 11 和玩家 22 被观察到,共 22 人被观察到。

对于 22 号点,没有玩家在第 22 秒时在此结点,共 00 人被观察到。

对于 33 号点,没有玩家在第 55 秒时在此结点,共 00 人被观察到。

对于 44 号点,玩家 11 被观察到,共 11 人被观察到。

对于 55 号点,玩家 11 被观察到,共 11 人被观察到。

对于 66 号点,玩家 33 被观察到,共 11 人被观察到。

样例二

input

5 3
1 2
2 3
2 4
1 5
0 1 0 3 0
3 1
1 4
5 5

output

1 2 1 0 1

限制与约定

每个测试点的数据规模及特点如下表所示。提示:数据范围的个位上的数字可以帮助判断是哪一种数据类型。

测试点编号 nn mm 约定
1 =991=991 =991=991 所有人的起点等于自己的终点,即 Si=TiSi=Ti
2
3 =992=992 =992=992 Wj=0Wj=0
4
5 =993=993 =993=993
6 =99994=99994 =99994=99994 树退化成一条链,其中 11 与 22 有边,22 与 33 有边,……,n−1n−1 与 nn 有边
7
8
9 =99995=99995 =99995=99995 所有的 Si=1Si=1
10
11
12
13 =99996=99996 =99996=99996 所有的 Ti=1Ti=1
14
15
16
17 =99997=99997 =99997=99997
18
19
20 =299998=299998 =299998=299998

时间限制:2s2s

空间限制:512MB512MB

【题解】

网上题解很多,就不赘述了

推荐http://www.cnblogs.com/ljh2000-jump/p/6184170.html

这个题 UOJ  洛谷 AC  BZOJ  WA

不管了!

后记:BZOJ WA是因为我并查集的fa跟着边一起赋的初始值,于是还要f[n] = n

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? (-1 * (a)) : a) inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '')c = ch, ch = getchar();
while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();
if(c == '-')x = -x;
} const int INF = 0x3f3f3f3f;
const int MAXN = + ;
const int MAXM = + ;
const int PIANYI = ; struct Edge
{
int u,v,next;
Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;}
Edge(){}
}edge[MAXN << ];
int head[MAXN], cnt;
inline void insert(int a, int b)
{
edge[++cnt] = Edge(a,b,head[a]);
head[a] = cnt;
} struct qEdge
{
int u,v,next,id;
qEdge(int _u, int _v, int _next, int _id){u = _u;v = _v;next = _next;id = _id;}
qEdge(){}
}qedge[MAXN << ];
int qhead[MAXN], qcnt = ;
inline void qinsert(int a, int b, int id)
{
qedge[++qcnt] = qEdge(a,b,qhead[a],id);
qhead[a] = qcnt;
} int n,m,tong[];
std::vector<int> vec[MAXN];
std::vector<int> end[MAXN]; struct Node
{
int s, t, lca, lenth;
}node[MAXM]; int w[MAXN],fa[MAXN],b[MAXN],deep[MAXN]; int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
} void dfs2(int u)
{
b[u] = ;
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v])continue;
deep[v] = deep[u] + ;
dfs2(v);
int f1 = find(u), f2 = find(v);
fa[f2] = f1;
}
for(register int pos = qhead[u];pos;pos = qedge[pos].next)
{
int v = qedge[pos].v, tmp = find(v);
node[qedge[pos].id].lca = tmp;
node[qedge[pos].id].lenth = deep[u] + deep[v] - * deep[tmp];
}
} void tarjan_lca()
{
deep[] = ;
dfs2();
} int ans[MAXN],s[MAXN];
//ans[i]表示i这个点能看到多少人,s[i]表示在i这个点有几个起点,t[i]表示在i这个点有几个终点 void dfs1(int u)
{
b[u] = ;
int tmp1;
tmp1 = tong[deep[u] + w[u]];
//递归子节点
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v]) continue;
dfs1(v);
}
tong[deep[u]] += s[u];
ans[u] += tong[deep[u] + w[u]] - tmp1;
//把以u为LCA的路径删除掉
for(register int i = vec[u].size() - ;i >= ;-- i)
-- tong[deep[node[vec[u][i]].s]];
} void dfs3(int u)
{
b[u] = ;
int tmp2;
tmp2 = tong[w[u] - deep[u] + PIANYI];
//递归子节点
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v]) continue;
dfs3(v);
}
for(register int i = end[u].size() - ;i >= ;-- i)
++ tong[node[end[u][i]].lenth - deep[u] + PIANYI];
ans[u] += tong[w[u] - deep[u] + PIANYI] - tmp2;
for(register int i = vec[u].size() - ;i >= ;-- i)
-- tong[node[vec[u][i]].lenth - deep[node[vec[u][i]].t] + PIANYI];
} int main()
{
read(n), read(m);
for(register int i = ;i < n;++ i)
{
int tmp1, tmp2;
read(tmp1), read(tmp2);
insert(tmp1, tmp2);
insert(tmp2, tmp1);
fa[i] = i;
}
for(register int i = ;i <= n;++ i)
read(w[i]);
for(register int i = ;i <= m;++ i)
{
read(node[i].s), read(node[i].t);
qinsert(node[i].s, node[i].t, i);
qinsert(node[i].t, node[i].s, i);
++ s[node[i].s];
}
tarjan_lca();
for(register int i = ;i <= n;++ i)
vec[node[i].lca].push_back(i), end[node[i].t].push_back(i);
memset(b, , sizeof(b));
dfs1();
memset(b, , sizeof(b));
dfs3();
for(register int i = ;i <= m;++ i)
if(deep[node[i].s] == deep[node[i].lca] + w[node[i].lca])
-- ans[node[i].lca];
for(register int i = ;i < n;++ i)
printf("%d ", ans[i]);
printf("%d", ans[n]);
return ;
}

天天爱跑步 BZOJ未AC

BZOJ AC:

 #include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(a) ((a) < 0 ? (-1 * (a)) : a) inline void read(int &x)
{
x = ;char ch = getchar(), c = ch;
while(ch < '' || ch > '')c = ch, ch = getchar();
while(ch <= '' && ch >= '')x = x * + ch - '', ch = getchar();
if(c == '-')x = -x;
} const int INF = 0x3f3f3f3f;
const int MAXN = + ;
const int MAXM = + ;
const int PIANYI = ; struct Edge
{
int u,v,next;
Edge(int _u, int _v, int _next){u = _u;v = _v;next = _next;}
Edge(){}
}edge[MAXN << ];
int head[MAXN], cnt;
inline void insert(int a, int b)
{
edge[++cnt] = Edge(a,b,head[a]);
head[a] = cnt;
} struct qEdge
{
int u,v,next,id;
qEdge(int _u, int _v, int _next, int _id){u = _u;v = _v;next = _next;id = _id;}
qEdge(){}
}qedge[MAXN << ];
int qhead[MAXN], qcnt = ;
inline void qinsert(int a, int b, int id)
{
qedge[++qcnt] = qEdge(a,b,qhead[a],id);
qhead[a] = qcnt;
} int n,m,tong[],ma;
std::vector<int> vec[MAXN];
std::vector<int> end[MAXN]; struct Node
{
int s, t, lca, lenth;
}node[MAXM]; int w[MAXN],fa[MAXN],b[MAXN],deep[MAXN]; int find(int x)
{
return x == fa[x] ? x : fa[x] = find(fa[x]);
} void dfs2(int u)
{
b[u] = ;
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v])continue;
deep[v] = deep[u] + ;
ma = max(ma, deep[v]);
dfs2(v);
int f1 = find(u), f2 = find(v);
fa[f2] = f1;
}
for(register int pos = qhead[u];pos;pos = qedge[pos].next)
{
int v = qedge[pos].v, tmp = find(v);
node[qedge[pos].id].lca = tmp;
node[qedge[pos].id].lenth = deep[u] + deep[v] - * deep[tmp];
}
} void tarjan_lca()
{
deep[] = ;
dfs2();
} int ans[MAXN],s[MAXN];
//ans[i]表示i这个点能看到多少人,s[i]表示在i这个点有几个起点,t[i]表示在i这个点有几个终点 void dfs1(int u)
{
b[u] = ;
int tmp1;
if(deep[u] + w[u] <= ma)tmp1 = tong[deep[u] + w[u]];
//递归子节点
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v]) continue;
dfs1(v);
}
tong[deep[u]] += s[u];
if(deep[u] + w[u] <= ma) ans[u] += tong[deep[u] + w[u]] - tmp1;
//把以u为LCA的路径删除掉
for(register int i = vec[u].size() - ;i >= ;-- i)
-- tong[deep[node[vec[u][i]].s]];
} void dfs3(int u)
{
b[u] = ;
int tmp2;
tmp2 = tong[w[u] - deep[u] + PIANYI];
//递归子节点
for(register int pos = head[u];pos;pos = edge[pos].next)
{
int v = edge[pos].v;
if(b[v]) continue;
dfs3(v);
}
for(register int i = end[u].size() - ;i >= ;-- i)
++ tong[node[end[u][i]].lenth - deep[u] + PIANYI];
ans[u] += tong[w[u] - deep[u] + PIANYI] - tmp2;
for(register int i = vec[u].size() - ;i >= ;-- i)
-- tong[node[vec[u][i]].lenth - deep[node[vec[u][i]].t] + PIANYI];
} int main()
{
read(n), read(m);
for(register int i = ;i < n;++ i)
{
int tmp1, tmp2;
read(tmp1), read(tmp2);
insert(tmp1, tmp2);
insert(tmp2, tmp1);
}
for(register int i = ;i <= n;++ i)
read(w[i]), fa[i] = i;
for(register int i = ;i <= m;++ i)
{
read(node[i].s), read(node[i].t);
qinsert(node[i].s, node[i].t, i);
qinsert(node[i].t, node[i].s, i);
++ s[node[i].s];
}
tarjan_lca();
for(register int i = ;i <= n;++ i)
vec[node[i].lca].push_back(i), end[node[i].t].push_back(i);
memset(b, , sizeof(b));
dfs1();
memset(b, , sizeof(b));
dfs3();
for(register int i = ;i <= m;++ i)
if(deep[node[i].s] == deep[node[i].lca] + w[node[i].lca])
-- ans[node[i].lca];
for(register int i = ;i < n;++ i)
printf("%d ", ans[i]);
printf("%d", ans[n]);
return ;
}

BZOJ AC

最新文章

  1. JAVA 设计模式 备忘录模式
  2. Linux中printf格式化输出
  3. 转载:50个C/C++源代码网站
  4. 自定义View等待旋转
  5. T-SQL使用JOIN执行UPDATE语句
  6. Eclipse 中隐藏的 5 个非常有用的功能
  7. sql sever 随机查询
  8. 如何设置ubuntu自己主动的睡眠时间
  9. 安装配置Postgresql
  10. canvas基础语法
  11. c#之文件操作(学习笔记)
  12. SpringBoot添加自定义拦截器
  13. Maven 通过maven对项目进行拆分、聚合(重点)
  14. bzoj 2202 [HNOI2010] Bounce 弹飞绵羊(分块)
  15. Ubuntu/Unity中更改窗口修饰键Alt为Super
  16. JS 如何将“在线图片资源”转换成“base64”
  17. powerdesigner mysql逆向工程注释不显示问题
  18. PHPStorm 中配置 XDebug
  19. JobTracker和TaskTracker
  20. Atcoder 2159 連結 / Connectivity(并查集+map乱搞)

热门文章

  1. laravel框架5.5 连接redis和redis集群
  2. 关于新手必须要理解的几个名词,cookie、session和token
  3. MyEclipse使用总结——在MyEclipse中新建Maven框架的web项目[转]
  4. System.Web.Mvc.RedirectResult.cs
  5. IDEA本地SBT项目上传到SVN
  6. java笔试之求int型正整数在内存中存储时1的个数
  7. Leetcode 345 Reverse Vowels in a String
  8. JDK中有关23个经典设计模式的示例
  9. 交叉熵-loss-理解
  10. 901. Online Stock Span [短于线性的时间统计单个元素的Span ]