NOIP 2016 天天爱跑步 80分暴力
题目描述
小c同学认为跑步非常有趣,于是决定制作一款叫做《天天爱跑步》的游戏。«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务。
这个游戏的地图可以看作一一棵包含 个结点和
条边的树, 每条边连接两个结点,且任意两个结点存在一条路径互相可达。树上结点编号为从
到
的连续正整数。
现在有个玩家,第
个玩家的起点为
,终点为
。每天打卡任务开始时,所有玩家在第
秒同时从自己的起点出发, 以每秒跑一条边的速度, 不间断地沿着最短路径向着自己的终点跑去, 跑到终点后该玩家就算完成了打卡任务。 (由于地图是一棵树, 所以每个人的路径是唯一的)
小C想知道游戏的活跃度, 所以在每个结点上都放置了一个观察员。 在结点的观察员会选择在第
秒观察玩家, 一个玩家能被这个观察员观察到当且仅当该玩家在第
秒也理到达了结点
。 小C想知道每个观察员会观察到多少人?
注意: 我们认为一个玩家到达自己的终点后该玩家就会结束游戏, 他不能等待一 段时间后再被观察员观察到。 即对于把结点作为终点的玩家: 若他在第
秒重到达终点,则在结点
的观察员不能观察到该玩家;若他正好在第
秒到达终点,则在结点
的观察员可以观察到这个玩家。
输入输出格式
输入格式:
第一行有两个整数和
。其中
代表树的结点数量, 同时也是观察员的数量,
代表玩家的数量。
接下来 行每行两个整数
和
,表示结点
到结点
有一条边。
接下来一行 个整数,其中第
个整数为
, 表示结点
出现观察员的时间。
接下来 行,每行两个整数
,和
,表示一个玩家的起点和终点。
对于所有的数据,保证 。
输出格式:
输出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
2 0 0 1 1 1
5 3
1 2
2 3
2 4
1 5
0 1 0 3 0
3 1
1 4
5 5
1 2 1 0 1
说明
【样例1说明】
对于1号点,,故只有起点为1号点的玩家才会被观察到,所以玩家1和玩家2被观察到,共有2人被观察到。
对于2号点,没有玩家在第2秒时在此结点,共0人被观察到。
对于3号点,没有玩家在第5秒时在此结点,共0人被观察到。
对于4号点,玩家1被观察到,共1人被观察到。
对于5号点,玩家1被观察到,共1人被观察到。
对于6号点,玩家3被观察到,共1人被观察到。
【子任务】
每个测试点的数据规模及特点如下表所示。 提示: 数据范围的个位上的数字可以帮助判断是哪一种数据类型。

【提示】
如果你的程序需要用到较大的栈空问 (这通常意味着需要较深层数的递归), 请务必仔细阅读选手日录下的文本当rumung:/stact.p″, 以了解在最终评测时栈空问的限制与在当前工作环境下调整栈空问限制的方法。
在最终评测时,调用栈占用的空间大小不会有单独的限制,但在我们的工作
环境中默认会有 8 MB 的限制。 这可能会引起函数调用层数较多时, 程序发生
栈溢出崩溃。
我们可以使用一些方法修改调用栈的大小限制。 例如, 在终端中输入下列命
令 ulimit -s 1048576
此命令的意义是,将调用栈的大小限制修改为 1 GB。
例如,在选手目录建立如下 sample.cpp 或 sample.pas

将上述源代码编译为可执行文件 sample 后,可以在终端中运行如下命令运
行该程序
./sample
如果在没有使用命令“ ulimit -s 1048576”的情况下运行该程序, sample
会因为栈溢出而崩溃; 如果使用了上述命令后运行该程序,该程序则不会崩溃。
特别地, 当你打开多个终端时, 它们并不会共享该命令, 你需要分别对它们
运行该命令。
请注意, 调用栈占用的空间会计入总空间占用中, 和程序其他部分占用的内
存共同受到内存限制。
思路:
这题真特么恶心;
明明noi难度的题非要搞到noip里;
这题一看范围就懵了;
然后,我们就开始写暴力;
看第一个数据,n<=1000;
恩,纯暴力就好,找两点的lca,往上跳的同时观察;
看第二个数据,树退化成了链;
按说树退化成了链,应该是更好做一些,然而,蒟蒻不会;
最后蒟蒻的做法是
枚举每个点;
每个点的可以被观察到时,这条路径的起点是却定的;
所以,我们只需判断这个起点的路径是否包括这个点;
可能被极限数据卡成n*n,但是出题人还是很良心的;
看第三个数据,路径起点都是1;
当起点都是1的时候;
对整棵树以1为根开始树剖;
然后,我们就发现,每个点的深度就是这个点上的人跑的时间;
然后判断wi是否等于deepi就好;
看第4个数据,路径终点都是1;
这个就有点恶心了;
但是我还是拿到了手;
我们先进行dfs,把树上每个节点的子树都用区间表示;
然后针对每个深度建立一颗线段树;
然后,用当树为链时判断起点的方法判断起点在哪个深度;
然后用线段树logn求出;
恩,水到80分了;
剩下20分死活水不出来;
来,上代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define maxn 100005
#define maxn1 1005
//暴力dfs
#define maxn2 99994
//树变成一条链
#define maxn3 99995
//所有si=1
#define maxn4 99996
//所有ti=1 using namespace std; struct STreeNodeType {
int l,r,dis,lc,rc;
};
struct STreeNodeType stree[maxn*]; struct TreeNodeType {
int l,r,dis,mid,flag;
};
struct TreeNodeType tree[maxn<<]; struct ListType {
int e,v;
};
struct ListType eli[maxn]; int root[maxn],li[maxn],ri[maxn];
int n,m,head[maxn],E[maxn<<],V[maxn<<],cnt,apti[maxn];
int f[maxn],deep[maxn],dfn[maxn],fdfn,times[maxn],tot;
int lis[maxn],size[maxn],top[maxn],bel[maxn],id[maxn]; char Cget; inline void in(int &now)
{
now=,Cget=getchar();
while(Cget>''||Cget<'') Cget=getchar();
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
} void dfs_dfn(int now,int fa)
{
f[now]=fa,deep[now]=deep[fa]+,dfn[now]=++fdfn;
for(int i=head[now];i;i=E[i])
{
if(V[i]==fa) continue;
dfs_dfn(V[i],now);
}
} inline void slca(int x,int y)
{
int x_=x,y_=y,lca,ti=;
while(dfn[x_]!=dfn[y_])
{
if(dfn[x_]<dfn[y_]) swap(x_,y_);
while(dfn[x_]>dfn[y_]) x_=f[x_];
}
lca=x_;
while(x!=lca)
{
if(ti==apti[x]) times[x]++;
x=f[x],ti++;
}
if(ti==apti[lca]) times[lca]++;
ti+=deep[y]-deep[lca];
while(y!=lca)
{
if(ti==apti[y]) times[y]++;
y=f[y],ti--;
}
} void dfs_tree(int now,int fa)
{
int pos=cnt++;
f[now]=fa;
deep[now]=deep[fa]+;
for(int i=head[now];i;i=E[i])
{
if(V[i]==fa) continue;
dfs_tree(V[i],now);
}
size[now]=cnt-pos;
} void dfs_tree_(int now,int chain)
{
int pos=;
top[now]=chain,bel[++cnt]=now,id[now]=cnt;
for(int i=head[now];i;i=E[i])
{
if(V[i]==f[now]) continue;
if(size[V[i]]>size[pos]) pos=V[i];
}
if(pos==) return ;
dfs_tree_(pos,chain);
for(int i=head[now];i;i=E[i])
{
if(V[i]==pos||V[i]==f[now]) continue;
dfs_tree_(V[i],V[i]);
}
} inline void tree_down(int now)
{
if(tree[now].l==tree[now].r) return ;
tree[now<<].flag+=tree[now].flag;
tree[now<<|].flag+=tree[now].flag;
tree[now<<].dis+=tree[now].flag*(tree[now<<].r-tree[now<<].l+);
tree[now<<|].dis+=tree[now].flag*(tree[now<<|].r-tree[now<<|].l+);
tree[now].flag=;
} void tree_build(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r;
if(l==r) return ;
tree[now].mid=l+r>>;
tree_build(now<<,l,tree[now].mid);
tree_build(now<<|,tree[now].mid+,r);
} void tree_change(int now,int l,int r)
{
if(tree[now].l==l&&tree[now].r==r)
{
tree[now].flag++;
tree[now].dis+=r-l+;
return ;
}
if(tree[now].flag) tree_down(now);
if(l>tree[now].mid) tree_change(now<<|,l,r);
else if(r<=tree[now].mid) tree_change(now<<,l,r);
else
{
tree_change(now<<,l,tree[now].mid);
tree_change(now<<|,tree[now].mid+,r);
}
tree[now].dis=tree[now<<].dis+tree[now<<|].dis;
} void solve_add(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[x]<deep[y]) swap(x,y);
tree_change(,id[top[x]],id[x]);
x=f[top[x]];
}
if(deep[x]>deep[y]) swap(x,y);
tree_change(,id[x],id[y]);
} void tree_count_si(int now)
{
if(tree[now].l==tree[now].r)
{
if(deep[bel[tree[now].l]]==apti[bel[tree[now].l]])
{
times[bel[tree[now].l]]+=tree[now].dis;
}
return ;
}
if(tree[now].flag) tree_down(now);
tree_count_si(now<<);
tree_count_si(now<<|);
} void st_add(int &now,int l,int r,int to,int x)
{
if(now==)
{
now=++tot;
stree[now].l=l,stree[now].r=r;
}
stree[now].dis+=x;
if(l==r) return ;
int mid=l+r>>;
if(to>mid) st_add(stree[now].rc,mid+,r,to,x);
else st_add(stree[now].lc,l,mid,to,x);
} void dfs_ti(int now,int fa)
{
li[now]=++cnt,deep[now]=deep[fa]+;
st_add(root[deep[now]],,n,li[now],size[now]);
for(int i=head[now];i;i=E[i])
{
if(V[i]==fa) continue;
dfs_ti(V[i],now);
}
ri[now]=cnt;
} int query(int now,int l,int r)
{
if(now==) return ;
if(stree[now].l==l&&stree[now].r==r) return stree[now].dis;
int mid=stree[now].l+stree[now].r>>;
if(l>mid) return query(stree[now].rc,l,r);
else if(r<=mid) return query(stree[now].lc,l,r);
else return query(stree[now].lc,l,mid)+query(stree[now].rc,mid+,r);
} int main()
{
in(n),in(m);int u,v;
for(int i=;i<n;i++)
{
in(u),in(v);
V[++cnt]=v,E[cnt]=head[u],head[u]=cnt;
V[++cnt]=u,E[cnt]=head[v],head[v]=cnt;
}
for(int i=;i<=n;i++) in(apti[i]);
if(n<=maxn1)
{
dfs_dfn(,);
while(m--)
{
in(u),in(v);
slca(u,v);
}
for(int i=;i<=n;i++) printf("%d ",times[i]);
}else if(n==maxn2)
{
cnt=;
while(m--)
{
in(u),in(v);
eli[++cnt].v=v,eli[cnt].e=lis[u],lis[u]=cnt;
}
for(int i=;i<=n;i++)
{
u=i-apti[i],v=i+apti[i];
if(u>)
{
for(int j=lis[u];j;j=eli[j].e)
{
if(eli[j].v>=i) times[i]++;
}
}
if(v<=n)
{
for(int j=lis[v];j;j=eli[j].e)
{
if(eli[j].v<=i) times[i]++;
}
}
printf("%d ",times[i]);
}
}else if(n==maxn3)
{
deep[]=-;
cnt=,dfs_tree(,);
cnt=,dfs_tree_(,);
tree_build(,,n);
while(m--)
{
in(u),in(v);
solve_add(u,v);
}
tree_count_si();
for(int i=;i<=n;i++) printf("%d ",times[i]);
}else if(n==maxn4)
{
while(m--)
{
in(u),in(v);
size[u]++;
}
deep[]=;
cnt=,tot=,dfs_ti(,);
for(int i=;i<=n;i++)
{
int pos=deep[i]+apti[i];
printf("%d ",query(root[pos],li[i],ri[i]));
}
}
return ;
}
NOIP 2016 天天爱跑步 80分暴力的更多相关文章
- NOIP2016 天天爱跑步 80分暴力
https://www.luogu.org/problem/show?pid=1600 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养 ...
- [NOIP]2016天天爱跑步
[NOIP]2016天天爱跑步 标签: LCA 树上差分 NOIP Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...
- Noip 2016 天天爱跑步 题解
[NOIP2016]天天爱跑步 时间限制:2 s 内存限制:512 MB [题目描述] 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是 ...
- [NOIp 2016]天天爱跑步
Description 小C同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图 ...
- NOIP 2016 天天爱跑步 (luogu 1600 & uoj 261) - 线段树
题目传送门 传送点I 传送点II 题目大意 (此题目不需要大意,我认为它已经很简洁了) 显然线段树合并(我也不知道哪来这么多显然) 考虑将每条路径拆成两条路径 s -> lca 和 t -> ...
- 【NOIP】提高组2016 天天爱跑步
[题意]n个点的树,有m个人同时开始走链,每一步花一秒,n个点都有观察员在ai秒观察,求每个观察员观察到的人数. [算法]树上差分(主席树||线段树合并) [题解]一个人的走链可以拆成u-lca和lc ...
- 【noip 2016】 蚯蚓(50分)(earthworm)
50分小程序,写了2天- 题目在这里 一个单调队列,写的都是p=0的点,考试的时候要是弄到这些分的话--不说了-- 羡慕AC的神犇啊,54行的满分程序,而我-- #include <iostre ...
- [luogu]P1600 天天爱跑步[LCA]
[luogu]P1600 [NOIP 2016]天天爱跑步 题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上 ...
- [NOIP2016-day1-T2]天天爱跑步running_题解
题目来源:http://www.lydsy.com/JudgeOnline/problem.php?id=4719 镇楼图: noip滚粗后..订正的第一题. 题目大意: 有若干条路径在一棵树上,问每 ...
随机推荐
- manjaro中文输入法已安装但切换不了解决方法
情况如图所示,输入法安装了,但Ctrl+空格键或者鼠标选择切换都不行 解决方法: 打开家目录下面的.xprofile文件,如果没有这个文件就新建一个,加入下面内容 保存文件,退出. 重启电脑就可以了
- libevent源码分析1 ----evnet相关结构体分析
位于代码event-internal.h中. event_base类似事件的集合,你创建一个事件,必须将该事件指定一个集合. struct event_base { 50 const stru ...
- Codeforces Round #459 (Div. 2):B. Radio Station
B. Radio Station time limit per test2 seconds memory limit per test256 megabytes Problem Dsecription ...
- MVC中Spring.net 对基类控制器无效 过滤器控制器无效
比如现在我又一个BaseController作为基类控制器,用于过滤权限.登录判断等作用,其它控制由原本的继承Controller,改为继承BaseController.然后BaseControlle ...
- laravel5.2总结--集合
类(Laravel集合基类) Illuminate\Support\Collection 类提供一个流畅.便利的封装来操控数组数据,官方提供了很多辅助函数,方便对数据进行各种处理,Coll ...
- 想进BAT?这些面试题助你一臂之力
1 软性热身题 这种题目,考的就是你的软性能力,比如表达能力,理解能力,协调能力,一个词概括就是套路.这类题目会在面试开始热身的时候,问一道两题,不会多,但是如果你能回答的有条不紊,清晰达意,那么就会 ...
- java作业8
interface Pet{ public String getName(); public String getColor(); public int getAge(); } class Cat i ...
- 来自知乎的pthread_cond_wait为什么总是带着mutex
来自https://www.zhihu.com/question/24116967?q=linux%20%E5%A4%9A%E7%BA%BF%E7%A8%8B%20%E8%99%9A%E5%81 ...
- Log4j官方文档翻译(四、如何在java中输出日志消息)
我们已经创建来配置文件,本章详细的介绍下如何生成调试信息,并把他们转化成文本文件. 基本的例子 下面就是创建的一个基本的例子: log4j.properties的内容为: log = /usr/hom ...
- 【bzoj2096】[Poi2010]Pilots 双指针法+STL-set
题目描述 Tz又耍畸形了!!他要当飞行员,他拿到了一个飞行员测试难度序列,他设定了一个难度差的最大值,在序列中他想找到一个最长的子串,任意两个难度差不会超过他设定的最大值.耍畸形一个人是不行的,于是他 ...