NOIP2017提高组模拟赛 10 (总结)
NOIP2017提高组模拟赛 10 (总结)##
第一题 机密信息
FJ有个很奇怪的习惯,他把他所有的机密信息都存放在一个叫机密盘的磁盘分区里,然而这个机密盘中却没有一个文件,那他是怎么存放信息呢?聪明的你一定想到了,FJ的信息都是以文件夹名称的形式保存的。FJ给机密盘中的每一个文件夹都编了号,而FJ的机密信息是由S文件夹转到T文件夹的过程中必须经过的文件夹名称组合而成的,由于FJ的磁盘很慢,打开每个文件夹所耗费的时间等于该文件夹内下一级文件夹的数量。这次的任务是,给出每个文件夹的编号、名称以及它的父目录的编号和隐藏了FJ机密信息的起始文件夹编号和终点文件夹编号,你要计算出来的是FJ机密信息的长度以及寻找这个机密信息所需要的总时间。假设你一开始就在起始文件夹位置,此时耗费的时间为0;你每打开一个文件夹,能够知道的文件夹名除了当前这个文件夹名之外,还有该文件夹内下一级的文件夹名。
一道简单的模拟题,暴力找S、T的lca,将路径上的点的值累加。
是S已经打开,到看到T(也就是打开了T的父亲)的路径。
注意一些特殊情况:
①S是T的祖先,或T是S的祖先。
②S和T的祖先不为S或T(需要减掉T打开的时间)。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
typedef long long ll;
using namespace std;
const int N=10050;
int n,S,T,ti[N],tim,fa[N],out[N];
int ls[N],to[N],ne[N],h[N],tt;
int anstime,anslen;
char st[310];
void add(int a,int b) { to[++tt]=b; ne[tt]=h[a]; h[a]=tt; }
void dfs(int x,int ff)
{
ti[x]=++tim;
for(int p=h[x];p;p=ne[p])
{
int v=to[p];
if(v==ff) continue;
dfs(v,x);
}
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d%d%d",&n,&S,&T);
n++; S++; T++; tt=1;
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d%s",&a,&b,st);
a++; b++; ls[a]=strlen(st);
fa[a]=b; out[b]++; add(b,a);
}
fa[1]=0; tim=0;
dfs(1,1);
if(S==T)
{
printf("%d\n",ls[S]);
printf("0\n");
} else
{
int fs=S,ft=T;
anstime=-out[S]; anslen=0;
if(ti[S]<ti[T]) swap(S,T);
while(ti[fa[S]]>ti[T])
{
anstime+=out[S]; anslen+=ls[S];
S=fa[S];
}
anstime+=out[S]; anslen+=ls[S];
S=fa[S];
while(T!=S)
{
anstime+=out[T]; anslen+=ls[T];
T=fa[T];
}
anstime+=out[T]; anslen+=ls[T];
if(ti[T]!=ti[ft]) anstime-=out[ft];
printf("%d\n",anslen);
printf("%d\n",anstime);
}
return 0;
}
第二题 路由器
Farmer John最近买了些新电脑,它向为奶牛们提供上网的机会,但是上网需要路由器,FJ想尽量少买路由器。FJ 有N个(1<=N<=100,000)(编号为1..N)个农场,由N-1条长度是1的边连接起来,没有环. FJ 可以决定把路由器放在哪些农场. 每个农场只有长度为 K (0<=K<=10)的网线,该农场可以连接到距离小于等于K的路由器. 路由器本身已经可以连接到互连网,可以被放置到任意的农场.
FJ至少要买多少个路由器,才能让每个农场都能上网?农场想要上网的话,至少要连接到一个包含路由器的农场.
因为这是一棵树,那么,优先处理最深的点一定是最优的,因为点x可以通过x的后代的路由器上网(而最低点不行)。
假如最低点为x,要放路由器,尽可能将其放在比较上的地方father[x][K]。因为既然x能到达,那么father[x][K]的其他后代也一定可以到达。而且放得越上,会对上方的点产生更多的贡献。
解法已经确立了:贪心。
①一种比较暴力的方法,先由最低点x开始,若vis[x]=0,则fa[x][L]装上路由器,ans++。拓展vis[],将可以用这个路由器上网的i的vis[i]标为1.
此方法的时间复杂度较为玄学,应该是不会超时的。vis[]会筛掉很多无用的点(即使重复标记也不会标记很多次的)。
②记录far[]和near[],表示(后代)未联网到当前点的最远的距离,以及最近到当前点的路由器距离。若far[x]+near[x]≤K则fa[x]=-∞,若far[x]=K则必须建立一个路由器(far[x]=-∞,near[x]=0),否则far[x]=(max far[xson])+1,near=(min near[xson])+1。
注:far[]=0,near[]=∞。(此方法是对方法①的一个优化,我也没有想到,是文同学想出来的。)
//方法①:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
typedef long long ll;
using namespace std;
const int N=100050;
int n,L,ans;
int fa[N][12],open[N],dep[N],he,ta;
int q[N],la,lb,bu[N];
int vis[N],bfstime;
bool ok[N];
int ne[N<<1],to[N<<1],h[N],tt;
void add(int a,int b) { to[++tt]=b; ne[tt]=h[a]; h[a]=tt; }
void bfs(int x)
{
he=ta=1; fa[x][1]=x;
open[1]=x; dep[x]=1; vis[x]=1;
while(he<=ta)
{
int u=open[he++];
for(int p=h[u];p;p=ne[p])
{
int v=to[p];
if(vis[v]!=0) continue;
vis[v]=1; dep[v]=dep[u]+1;
fa[v][1]=u; open[++ta]=v;
}
}
}
void expand(int x)
{
la=lb=1; q[1]=x; ok[x]=1;
vis[x]=++bfstime; bu[x]=0;
while(la<=lb)
{
int u=q[la++];
if(bu[u]>=L) continue;
for(int p=h[u];p;p=ne[p])
{
int v=to[p];
if(vis[v]==bfstime) continue;
vis[v]=bfstime; bu[v]=bu[u]+1;
q[++lb]=v; ok[v]=1;
}
}
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&n,&L); tt=1;
for(int i=1;i<n;i++)
{
int a,b; scanf("%d%d",&a,&b);
add(a,b); add(b,a);
}
bfs(1);
for(int i=1;i<=n;i++)
for(int j=2;j<=L;j++) fa[i][j]=fa[fa[i][j-1]][1];
bfstime=1;
for(int i=ta;i>=1;i--)
{
int u=open[i];
if(!ok[u])
{
ans++;
int yu=fa[u][L];
expand(yu);
}
}
printf("%d\n",ans);
return 0;
}
//PS:一开始bfs漏打了vis[x]=1,WA了两个点……
//方法②:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define imax(a,b) ((a>b)?(a):(b))
#define imin(a,b) ((a<b)?(a):(b))
typedef long long ll;
using namespace std;
const int oo=1e9;
const int N=100050;
int n,L,ans;
int open[N],he,ta;
int vis[N],fa[N],far[N],near[N];
int ne[N<<1],to[N<<1],h[N],tt;
void add(int a,int b) { to[++tt]=b; ne[tt]=h[a]; h[a]=tt; }
void bfs(int x)
{
he=ta=1; fa[x]=x;
open[1]=x; vis[x]=1;
while(he<=ta)
{
int u=open[he++]; vis[u]=2;
for(int p=h[u];p;p=ne[p])
{
int v=to[p];
if(vis[v]!=0) continue;
vis[v]=1; fa[v]=u; open[++ta]=v;
}
}
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&n,&L); tt=1;
for(int i=1;i<n;i++)
{
int a,b; scanf("%d%d",&a,&b);
add(a,b); add(b,a);
}
bfs(1);
ans=0;
for(int i=1;i<=n;i++) far[i]=0,near[i]=oo;
for(int i=ta;i>=1;i--)
{
int u=open[i];
if(vis[u]==1) continue;
if(far[u]+near[u]<=L) far[u]=-oo;
if(far[u]==L) near[u]=0,far[u]=-oo,ans++;
far[fa[u]]=imax(far[u]+1,far[fa[u]]);
near[fa[u]]=imin(near[u]+1,near[fa[u]]);
}
if(far[1]>0) ans++;
printf("%d\n",ans);
return 0;
}
第三题 骨牌游戏
X
NOIP2017提高组模拟赛 10 (总结)的更多相关文章
- NOIP2017提高组 模拟赛15(总结)
NOIP2017提高组 模拟赛15(总结) 第一题 讨厌整除的小明 [题目描述] 小明作为一个数学迷,总会出于数字的一些性质喜欢上某个数字,然而当他喜欢数字k的时候,却十分讨厌那些能够整除k而比k小的 ...
- NOIP2017提高组 模拟赛13(总结)
NOIP2017提高组 模拟赛13(总结) 第一题 函数 [题目描述] [输入格式] 三个整数. 1≤t<10^9+7,2≤l≤r≤5*10^6 [输出格式] 一个整数. [输出样例] 2 2 ...
- NOIP2017提高组模拟赛 9 (总结)
NOIP2017提高组模拟赛 9 (总结) 第一题 星星 天空中有N(1≤N≤400)颗星,每颗星有一个唯一的坐标(x,y),(1≤x,y ≤N).请计算可以覆盖至少K(1≤K≤N)颗星的矩形的最小面 ...
- NOIP2017提高组模拟赛5 (总结)
NOIP2017提高组模拟赛5 (总结) 第一题 最远 奶牛们想建立一个新的城市.它们想建立一条长度为N (1 <= N <= 1,000,000)的 主线大街,然后建立K条 (2 < ...
- NOIP2017提高组模拟赛4 (总结)
NOIP2017提高组模拟赛4 (总结) 第一题 约数 设K是一个正整数,设X是K的约数,且X不等于1也不等于K. 加了X后,K的值就变大了,你可以重复上面的步骤.例如K= 4,我们可以用上面的规则产 ...
- NOIP2017提高组模拟赛 8(总结)
NOIP2017提高组模拟赛 8(总结) 第一题 路径 在二维坐标平面里有N个整数点,Bessie要访问这N个点.刚开始Bessie在点(0,0)处. 每一步,Bessie可以走到上.下.左.右四个点 ...
- NOIP2017提高组模拟赛 7(总结)
NOIP2017提高组模拟赛 7(总结) 第一题 斯诺克 考虑这样一个斯诺克球台,它只有四个袋口,分别在四个角上(如下图所示).我们把所有桌子边界上的整数点作为击球点(除了4个袋口),在每个击球点我们 ...
- 计蒜客NOIP2017提高组模拟赛(三)day1
火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A1,A2,⋯,An点生命值,一次火山喷发总计 MM 轮 ...
- 计蒜客NOIP2017提高组模拟赛(四)day1
T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...
随机推荐
- html5开发手机打电话发短信功能,html5的高级开发,html5开发大全,html手机电话短信功能具体解释
在非常多的手机站点上,有打电话和发短信的功能,对于这些功能是怎样实现的呢.事实上不难,今天我们就用html5来实现他们. 简单的让你大开眼界.HTML5 非常easy写,但创建网页时,您常常须要反复做 ...
- java old GC和young GC
Java内存分配机制 摘自:http://www.cnblogs.com/zhguang/p/3257367.html 这里所说的内存分配,主要指的是在堆上的分配,一般的,对象的内存分配都是在堆上进行 ...
- C#.NET编码规范
一. 环境设置 首先去除开发环境中的一些选项如下: 图一 图二 二. 命名规范 1) 通用性 l 标识的总长度不要超过32个字符. l 标识符的基本语法是以字母和_开始,由字母数字及下划线组成的单词 ...
- SpringBoot(九) ElasticSearch 全文检索
ElasticSearch ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticsearch是用 ...
- iOS11中navigationBar上 按钮图片设置frame无效 不受约束 产生错位问题 解决
问题描述: 正常样式: 在iOS 11 iPhone X上显示效果: 观察顶部navBar上的左侧按钮 在ios 11 上 这个按钮的图片不受设置的尺寸约束,按其真实大小展示,造成图片错位,影响界 ...
- RabbitMQ基础学习笔记(C#代码示例)
一.定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发).MQ是一种应用程序对应用程序的通信方法.应用程序通过读写入队和出队的消息来通信,无需专 ...
- 使用 Object.create实现js 继承
二.Object.create实现继承 本文将来学习第七种继承方式Object.create()方法来实现继承,关于此方法的详细描述,请戳这里.下面来通过几个实例来学习该方法的使用: var Pare ...
- Eclipse中使用GIT提交文件至本地
GIT提交文件至本地: 1. 右击项目——Team——Commit…: 2.在弹出的Commit Changes框中——选择要提交的文件——填写提交说明——点击Commit,即可提交至本地.
- 通过页面预加载(preload)提升小程序的响应速度
GitHub: https://github.com/WozHuang/mp-extend 主要目标 如果小程序在打开新页面时需要通过网络请求从接口中获取所用的数据,在请求完成之前页面都会因为没有数据 ...
- 安装idea
1.下载idea https://www.jetbrains.com/idea/download/#section=linux 2.解压 sudo tar -zxvf ideaIC-2018.3.2 ...