NOIP 2015 提高组 Day2
期望得分:100+10+60=170
实际得分:100+10+35=145
http://www.cogs.pro/cogs/page/page.php?aid=16
T1 跳石头
时间限制:1 s 内存限制:256 MB
【题目描述】
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选
择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终 点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达 终点。
为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能 移走起点和终点的岩石)。
【输入格式】
输入文件第一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终 点之间的岩石数,以及组委会至多移走的岩石数。
接下来 N 行,每行一个整数,第 i 行的整数 Di(0 < Di < L)表示第 i 块岩石与 起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同 一个位置。
【输出格式】
输出文件只包含一个整数,即最短跳跃距离的最大值。
【样例输入】
25 5 2
2
11
14
17
21
【样例输出】
4
【提示】
输入输出样例 1 说明:将与起点距离为 2 和 14 的两个岩石移走后,最短的跳跃距离为 4(从与起点距离 17 的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。
另:对于 20%的数据,0 ≤ M ≤ N ≤ 10。 对于50%的数据,0 ≤ M ≤ N ≤ 100。
对于 100%的数据,0 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,000。
二分最短距离
如果两块石头间距离比二分的还要短,
若 此时还能移走石头,移走
否则return false
#include<cstdio>
#define N 50011
using namespace std;
int L,n,m,ans;
int a[N];
bool check(int k)
{
int last=,tot=;
for(int i=;i<=n+;i++)
if(a[i]-a[last]<k)
{
if(tot<m) tot++;
else return false;
}
else last=i;
return true;
}
int main()
{
scanf("%d%d%d",&L,&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
int l=,r=L,mid;
a[n+]=L;
while(l<=r)
{
mid=l+r>>;
if(check(mid)) ans=mid,l=mid+;
else r=mid-;
}
printf("%d",ans);
}
T2 子串
时间限制:1 s 内存限制:128 MB
【题目描述】
有两个仅包含小写英文字母的字符串 A 和 B。现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出现的顺序依次连接起来得到一 个新的字符串,请问有多少种方案可以使得这个新串与字符串 B 相等?注意:子串取出 的位置不同也认为是不同的方案。
【输入格式】
第一行是三个正整数 n,m,k,分别表示字符串 A 的长度,字符串 B 的长度,以及问题描述中所提到的 k,每两个整数之间用一个空格隔开。 第二行包含一个长度为 n 的字符串,表示字符串 A。 第三行包含一个长度为 m 的字符串,表示字符串 B。
【输出格式】
输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对 1,000,000,007 取模的结果。
【样例输入1】
6 3 1
aabaab
aab
【样例输出1】
2
【样例输入2】
6 3 2
aabaab
aab
【样例输出2】
7
【样例输入3】
6 3 3
aabaab
aab
【样例输出1】
7
【提示】
对于第 1 组数据:1≤n≤500,1≤m≤50,k=1;
对于第 2 组至第 3 组数据:1≤n≤500,1≤m≤50,k=2;
对于第 4 组至第 5 组数据:1≤n≤500,1≤m≤50,k=m;
对于第 1 组至第 7 组数据:1≤n≤500,1≤m≤50,1≤k≤m;
对于第 1 组至第 9 组数据:1≤n≤1000,1≤m≤100,1≤k≤m;
对于所有 10 组数据:1≤n≤1000,1≤m≤200,1≤k≤m。
令 f[i][j][k][0/1]表示A串前i个,分为k部分,匹配B串前j个,A串第i个不用/用 的方案数
状态转移方程:
如果i不用,那他就是前i-1个的和 f[i][j][k][0]=f[i-1][j][k][0]+f[i-1][j][k][1]
如果i用,条件是a[i]=b[j] 那么它有2种决策:自成一堆,与前一个合为一堆
自成一堆的话,他的前一个可能用了,也可能没用,又分为了两种
所以 f[i][j][k][1]= f[i-1][j-1][k-1][1](自成一堆,前一个用了)
+ f[i-1][j-1][k-1][0] (自成一堆,前一个没用)
+ f[i-1][j-1][k][1] (与前一个合为一堆,前一个必须用了)
边界条件:f[i][0][0][0]=1
边界研究了一晚上
f数组累积的前提是 a串中的第i个与b串的第一个相等
这时第i个只能自成一堆,f[i-1][1-1][k-1][0] = 1
最后用滚动数组滚动起来就A了
#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,p,ans,s;
char a[],b[];
int f[][][][];
const int mod=;
int main()
{
scanf("%d%d%d",&n,&m,&p);
scanf("%s%s",a+,b+);
f[][][][]=f[][][][]=;
for(int i=;i<=n;i++)
{
int t=i%;
for(int j=;j<=min(i,m);j++)
for(int k=;k<=min(j,p);k++)
{
f[t][j][k][]=(f[t^][j][k][]+f[t^][j][k][])%mod;
if(a[i]==b[j]) f[t][j][k][]=((f[t^][j-][k-][]+f[t^][j-][k-][])%mod+f[t^][j-][k][])%mod;
else f[t][j][k][]=;
}
ans=(ans+f[t][m][p][])%mod;
}
}
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int n, m, k;
long long f[][][], s[][][];
char a[], b[];
const int mod = ;
int main()
{
scanf("%d%d%d", &n, &m, &k);
scanf("%s", a + );
scanf("%s", b + );
int now = , last = ;
f[][][] = ;
for (int i = ; i <= n; i++)
{
f[now][][] = ;
for (int j = ; j <= min(i,m); j++)
for (int kk = ; kk <= min(j,k); kk++)
{
if (a[i] == b[j])
s[now][j][kk] = (s[last][j - ][kk] + f[last][j - ][kk - ]) % mod;
else
s[now][j][kk] = ;
f[now][j][kk] = (f[last][j][kk] + s[now][j][kk]) % mod;
}
swap(now, last);
}
printf("%lld\n", f[last][m][k]);
return ;
}
T3 运输计划
时间限制:1 s 内存限制:256 MB
【题目描述】
公元 2044 年,人类进入了宇宙纪元。
L 国有 n 个星球,还有 n-1 条双向航道,每条航道建立在两个星球之间,这 n-1 条航道连通了 L 国的所有星球。
小 P 掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物
流飞船需要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是需要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,并且任意两艘飞船之 间不会产生任何干扰。
为了鼓励科技创新,L 国国王同意小 P 的物流公司参与 L 国的航道建设,即允许小 P 把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。
在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,所有飞船一起出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工作就完成了。
如果小 P 可以自由选择将哪一条航道改造成虫洞,试求出小 P 的物流公司完成阶段 性工作所需要的最短时间是多少?
【输入格式】
第一行包括两个正整数 n、m,表示 L 国中星球的数量及小 P 公司预接的运输计划的数量,星球从 1 到 n 编号。
接下来 n-1 行描述航道的建设情况,其中第 i 行包含三个整数 ai, bi 和 ti,表示第i 条双向航道修建在 ai 与 bi 两个星球之间,任意飞船驶过它所花费的时间为 ti。 接下来 m 行描述运输计划的情况,其中第 j 行包含两个正整数 uj 和 vj,表示第 j 个运输计划是从 uj 号星球飞往 vj 号星球。
【输出格式】
共 1 行,包含 1 个整数,表示小 P 的物流公司完成阶段性工作所需要的最短时间。
【样例输入】
6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5
【样例输出】
11
【提示】
所有测试数据的范围和特点如下表所示
请注意常数因子带来的程序效率上的影响。
所需 技能:二分、lca、树链剖分、树上差分
求最值,很容易想到二分,那么我们就二分这个值k
如果最短时间为k,那么如果一个计划耗时超过k,那么它所经过的路径上就要有虫洞
可能有不止一个计划耗时超过k,
那么有可能改造为虫洞的路径是 所有超时的计划路径的交集
如果这个交集中有一条路径,耗时>= 超出的时间(即不建虫洞的最大耗时-二分值)
那么把他改为虫洞可以使时间减少
现在就差如何求 计划耗时 和 交集
计划耗时:树链剖分求lca,同时求出点到根节点的距离dis
计划耗时=dis[起点]+dis[终点]-2*dis[lca]
交集:树上差分
计划起点+1,终点+1,lca-2
然后从叶子节点向上累加
若点的sum等于超时计划数,则点与父节点之间的边在交集中
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define N 300001
using namespace std;
int n,m,l,r,mid,ans,maxn;
int front[N],nextt[N*],to[N*],tot,w[N*];
int son[N],fa[N],dis[N],deep[N];
int id[N],bl[N],cnt;
int sum[N];
struct node
{
int s,t,lca,dis;
}e[N];
void add(int u,int v,int x)
{
to[++tot]=v; nextt[tot]=front[u]; front[u]=tot; w[tot]=x;
}
void dfs(int x)
{
son[x]++;
for(int i=front[x];i;i=nextt[i])
{
if(to[i]==fa[x]) continue;
fa[to[i]]=x;
dis[to[i]]=dis[x]+w[i];
deep[to[i]]=deep[x]+;
dfs(to[i]);
son[x]+=son[to[i]];
}
}
void dfs2(int x,int top)
{
id[x]=++cnt;
bl[x]=top;
int y=;
for(int i=front[x];i;i=nextt[i])
{
if(to[i]==fa[x]) continue;
if(son[to[i]]>son[y]) y=to[i];
}
if(!y) return;
dfs2(y,top);
for(int i=front[x];i;i=nextt[i])
{
if(to[i]==fa[x]||to[i]==y) continue;
dfs2(to[i],to[i]);
}
}
void dfs3(int x)
{
for(int i=front[x];i;i=nextt[i])
{
if(to[i]==fa[x]) continue;
dfs3(to[i]);
sum[x]+=sum[to[i]];
}
}
int get_lca(int x,int y)
{
while(bl[x]!=bl[y])
{
if(deep[bl[x]]<deep[bl[y]]) swap(x,y);
x=fa[bl[x]];
}
if(deep[x]>deep[y]) x=y;
return x;
}
bool check(int k)
{
memset(sum,,sizeof(sum));
int h=;
for(int i=;i<=m;i++)
{
if(e[i].dis<=k) continue;
sum[e[i].s]++; sum[e[i].t]++; sum[e[i].lca]-=;
h++;
}
dfs3();
for(int i=;i<=n;i++) if(sum[i]==h&&dis[i]-dis[fa[i]]>=maxn-k) return true;
return false;
}
int main()
{
/*freopen("transport.in","r",stdin);
freopen("transport.out","w",stdout);*/
scanf("%d%d",&n,&m);
int u,v,a;
for(int i=;i<n;i++)
{
scanf("%d%d%d",&u,&v,&a);
add(u,v,a);
add(v,u,a);
}
for(int i=;i<=m;i++) scanf("%d%d",&e[i].s,&e[i].t);
dfs();
dfs2(,);
for(int i=;i<=m;i++)
{
e[i].lca=get_lca(e[i].s,e[i].t);
e[i].dis=dis[e[i].s]+dis[e[i].t]-*dis[e[i].lca];
maxn=max(maxn,e[i].dis);
}
r=maxn;
while(l<=r)
{
mid=l+r>>;
if(check(mid)) { ans=mid; r=mid-;}
else l=mid+;
}
printf("%d",ans);
}
NOIP 2015 提高组 Day2的更多相关文章
- NOIP 2015提高组复赛
神奇的幻方 题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第 ...
- noip 2015 提高组
算是填个坑吧 , QwQ Day 1 第一题很水,就是考代码能力 ,直接贴代码. #include <iostream> #include <cstdlib> #include ...
- noip 2013 提高组 Day2 部分题解
积木大赛: 之前没有仔细地想,然后就直接暴力一点(骗点分),去扫每一高度,连到一起的个数,于是2组超时 先把暴力程序贴上来(可以当对拍机) #include<iostream> #incl ...
- NOIP 2015 提高组 Day1
期望得分:100+100+100=300 实际得分:100+100+45=245 T3 相似的代码 复制过去 没有改全,痛失55分 http://www.cogs.pro/cogs/page/page ...
- NOIP 2013 提高组 day2 积木大赛
积木大赛 描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为 n 的大厦,大厦可以看成由 n 块宽度为1的积木组成,第
- noip 2012 提高组 day2 部分题解
这道题有多种解法,我用的是扩展欧几里得算法求到的答案 #include<iostream> #include<fstream> #include<cstdio> u ...
- NOIP 2014 提高组 Day2
期望得分:100+60+30=190 实际得分:70+60+30=160 https://www.luogu.org/problem/lists?name=&orderitem=pid& ...
- NOIP 2008提高组第三题题解by rLq
啊啊啊啊啊啊今天已经星期三了吗 那么,来一波题解吧 本题地址http://www.luogu.org/problem/show?pid=1006 传纸条 题目描述 小渊和小轩是好朋友也是同班同学,他们 ...
- [NOIp 1998 提高组]Probelm 2 连接多位数【2011百度实习生笔试题】
/*====================================================================== [NOIp 1998 提高组]Probelm 2 连接 ...
随机推荐
- 20181023-10 Alpha阶段第2周/共2周 Scrum立会报告+燃尽图 07
作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2290 Scrum master:范靖旋 一.小组介绍 组长:王一可 组员: ...
- DataGridView,Dataset,DataTable,DataRow等使用心得
DataGridView的列编辑: Name:用于调用属性的时候用的,也可以不使用Name去调用,选择数字1,2,3...选择第1列,第2列,第3列. HeaderText:表头显示的名字方便用户使用 ...
- 2018软工实践—Alpha冲刺(7)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 学习MSI.CUDA 试运行软件并调试 ...
- C++ Primer Plus学习:第七章
C++入门第七章:函数-C++的编程模块 函数的基本知识 要使用C++函数,必须完成如下工作: 提供函数定义 提供函数原型 调用函数 库函数是已经定义和编译好的函数,可使用标准库头文件提供原型. 定义 ...
- python接口自动化测试框架实现之字符串插入变量(字符串参数化)
问题: 在做接口自动化测试的时候,请求报文是json串,但是根据项目规则必须转换成字符串,然后在开头拼接“data=” 接口中很多入参值需要进行参数化. 解决方案: 1.Python并没有对在字符串中 ...
- css3 flex属性flex-grow、flex-shrink、flex-basis学习笔记
最近在研究css3的flex.遇到的flex:1;这一块,很是很纠结,flex-grow.flex-shrink.flex-basis始终搞不清,最经搜集了大量的介绍,应该能算是明白了.网上大部分解释 ...
- Tomcat安装及配置详解
Tomcat安装及配置详解 一,Tomcat简介 Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,Tomcat是Apache 软件基金会(Apache Software Found ...
- 使用ResourceBundle 类读取 src 下的 xxx.properties 文件
之前要读取 src 下的 .properties 文件都是使用的类加载器,加载类路径下的资源文件当做一个流来处理,load 到一个 Properties 对象上. jdbc.properties 代码 ...
- CPU测试--通过proc获取CPU信息
adb shell cat /proc/stat | grep cpu > totalcpu0 此处第一行的数值表示的是CPU总的使用情况,所以我们只要用第一行的数字计算就可以了.下表解析第一行 ...
- 【数据库】Mysql更改默认引擎为Innodb的步骤方法
前言 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定. 基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.M ...