总分   205分

T1 100分

T2  95分

T3  10分

T1:

题目描述

春春是一名道路工程师,负责铺设一条长度为 nn 的道路。

铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 nn 块首尾相连的区域,一开始,第 ii 块区域下陷的深度为 d_idi​ 。

春春每天可以选择一段连续区间[L,R][L,R] ,填充这段区间中的每块区域,让其下陷深度减少 11。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 00 。

春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为 00 。

输入格式

输入文件包含两行,第一行包含一个整数 nn,表示道路的长度。 第二行包含 nn 个整数,相邻两数间用一个空格隔开,第ii 个整数为 d_idi​ 。

输出格式

输出文件仅包含一个整数,即最少需要多少天才能完成任务。

输入输出样例

输入 #1复制

6
4 3 2 5 3 5
输出 #1复制

9

说明/提示

【样例解释】

一种可行的最佳方案是,依次选择: [1,6][1,6]、[1,6][1,6]、[1,2][1,2]、[1,1][1,1]、[4,6][4,6]、[4,4][4,4]、[4,4][4,4]、[6,6][6,6]、[6,6][6,6]。

【数据规模与约定】

对于 30% 的数据,1 ≤ n ≤ 10,1≤n≤10 ;
对于 70% 的数据,1 ≤ n ≤ 10001≤n≤1000 ;
对于 100% 的数据,1 ≤ n ≤ 100000 , 0 ≤ d_i ≤ 100001≤n≤100000,0≤di​≤10000 。

对于这个题来说,我其实一开始并不知道正解;然后我暴力A掉(数据的良心所在)

暴力思路:

现在对于一个坑,我们要去填平它,那么我们先看一下是否有地方已经被填平了,如果是的话,那么我们就填它两边的就行了,对于任意的一次填土,肯定是覆盖的区间越多越优,所以对于区间内没有被填平我们全部填上最靠近地面的那一个,也就是最小值;

复杂度 :O(log(n))随机数据

/*thanks for gods*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf 0x3f
using namespace std;
const int maxn=2e5+10;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int n,d[maxn];
long long ans=0;
void devide(int l,int r)
{
int end=0,pos=0,minn=10000,pos1;
for(int i=l;i<=r;i++)
{
if(d[i]==0)
{
pos=i;
end++;
}
if(minn>d[i])
{
minn=d[i],pos1=i;
}
}
if(end==r-l+1) return ;
if(!pos)
{
for(int i=l;i<=r;i++)
{
d[i]-=minn;
}
ans+=minn;
pos=pos1;
}
devide(l,pos-1);
devide(pos+1,r);
}
int main()
{
//freopen("road.in","r",stdin);
//freopen("road.out","w",stdout);
n=read();
for(int i=1;i<=n;i++)
d[i]=read();
devide(1,n);
printf("%d",ans);
return 0;
}

然后我抱着忐忑的心态,我认为拿到70分,结果A掉了

接下来就是正解思路 :

正解的思路也是差不了多少,也就是在一个坑中,如果是一个下降的数列,那么我们就填平,如果是上升的数列,那么对于上升的每一层数来说,一定已经被填平;枚举就OK了,

复杂度: O(n)

发现,我的好像更快


T2:

在网友的国度中共有  种不同面额的货币,第  种货币的面额为 ,你可以假设每一种货币都有无穷多张。为了方便,我们把货币种数为 、面额数组为  的货币系统记作 。

在一个完善的货币系统中,每一个非负整数的金额  都应该可以被表示出,即对每一个非负整数 ,都存在  个非负整数  满足  的和为 。然而, 在网友的国度中,货币系统可能是不完善的,即可能存在金额  不能被该货币系统表示出。例如在货币系统 ,  中,金额  就无法被表示出来。

两个货币系统  和  是等价的,当且仅当对于任意非负整数 ,它要么均可以被两个货币系统表出,要么不能被其中任何一个表出。

现在网友们打算简化一下货币系统。他们希望找到一个货币系统 ,满足  与原来的货币系统  等价,且  尽可能的小。他们希望你来协助完成这个艰巨的任务:找到最小的 。

输入格式

输入文件名为 money.in
输入文件的第一行包含一个整数 ,表示数据的组数。
接下来按照如下格式分别给出  组数据。 每组数据的第一行包含一个正整数 。接下来一行包含  个由空格隔开的正整数 。

输出格式

输出文件名为 money.out
输出文件共有  行,对于每组数据,输出一行一个正整数,表示所有与  等价的货币系统  中,最小的 。

样例

样例输入

2
4
3 19 10 6
5
11 29 13 19 17

样例输出

2
5

样例解释

在第一组数据中,货币系统  和给出的货币系统  等价,并可以验证不存在  的等价的货币系统,因此答案为 。

在第二组数据中,可以验证不存在  的等价的货币系统,因此答案为 。

数据范围与提示

对于全部数据,满足 。

解题思路:

对于这个题来说,我们要求从总货币系统(集合A)中求出一个货币系统(集合B),表示的数一样,且总数最小的,那么就很显然,B⊆A ;

那么我们的集合B中的任意一个元素,它只要能表示出A来,也就OK了,然后再注意看一下题面,无限张,那么很显然,我们就利用完全背包的思想就可以了,(不是多重背包,01背包是可以表示成完全背包的,而且这里也只是借用了完全背包的思想),那么,我们就设一个bool数组,f*

如果,f [ i ]为真,那么就意味着 i这个数可以被我们所选的货币系统也就是 集合B表示出来,如果不是,那么我们把这个数加入到集合B中来,

同时,对于判断 f [ i ] 是否为真,

这里先说一个结论,也是十分显而易见: 对于一个数  i  ,因为这个钱,money,好东西,不能减 ,所以i就要被比i小的数字的和表示出来,

所以说,先排序;!!!!!!!!!!!!!!!!

所以枚举 比 i小的数据,如果能凑出来,那么 i 减去这个数据能够凑出来,那么i 也一定能凑出来,所以状态转移方程也就是

    f [ i ] = f [ i ] | f [ j - a [ i ] ]

也可以写成:

        if ( f [ j - a [ i ] ] )  f [ j ] = 1 ;

然后就可以愉快的AC了,当时我讲的时候 ,我着实不知道咋讲。。QwQ

代码:

#include <bits/stdc++.h>
using namespace std;
int f[25000];
int a[200];
int mx=0;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int main()
{
freopen("money.in","r",stdin);
freopen("money.out","w",stdout);
int i,j,n,t,ans;
t=read();
while(t--)
{
ans=0;
memset(f,0,sizeof(f));
n=read();
for(i=1;i<=n;i++)
{
a[i]=read();
mx=max(mx,a[i]);
}
sort(a+1,a+n+1);
f[0]=1;
for(i=1;i<=n;i++)
{
if(f[a[i]])
{
continue;
}
ans++;
for(j=a[i];j<=mx;j++)
{
if(f[j-a[i]])
{
f[j]=1;
} }
}
printf("%d\n",ans);
}
return 0;
}

T3


这个题数据很很很良心,然后我骗了10分,

C 城将要举办一系列的赛车比赛。在比赛前,需要在城内修建  条赛道。

C 城一共有  个路口,这些路口编号为 ,有  条适合于修建赛道的双向通行的道路,每条道路连接着两个路口。其中,第  条道路连接的两个路口编号为  和 ,该道路的长度为 。借助这  条道路,从任何一个路口出发都能到达其他所有的路口。

一条赛道是一组互不相同的道路 ,满足可以从某个路口出发,依次经过道路 (每条道路经过一次,不允许调头)到达另一个路口。一条赛道的长度等于经过的各道路的长度之和。为保证安全,要求每条道路至多被一条赛道经过。

目前赛道修建的方案尚未确定。你的任务是设计一种赛道修建的方案,使得修建的  条赛道中长度最小的赛道长度最大(即  条赛道中最短赛道的长度尽可能大)。

输入格式

输入文件名为 track.in
输入文件第一行包含两个由空格分隔的正整数 ,分别表示路口数及需要修建的赛道数。
接下来  行,第  行包含三个正整数 ,表示第  条适合于修建赛道的道路连接的两个路口编号及道路长度。保证任意两个路口均可通过这  条道路相互到达。每行中相邻两数之间均由一个空格分隔。

输出格式

输出文件名为 track.out
输出共一行,包含一个整数,表示长度最小的赛道长度的最大值。

样例

样例输入 1

7 1
1 2 10
1 3 5
2 4 9
2 5 8
3 6 6
3 7 7

样例输出 1

31

样例解释 1

所有路口及适合于修建赛道的道路如下图所示:

道路旁括号内的数字表示道路的编号,非括号内的数字表示道路长度。

需要修建  条赛道。可以修建经过第  条道路的赛道(从路口  到路口 ),则该赛道的长度为 ,为所有方案中的最大值。

样例输入 2

9 3
1 2 6
2 3 3
3 4 5
4 5 10
6 2 4
7 2 9
8 4 7
9 4 4

样例输出 2

15

样例解释 2

所有路口及适合于修建赛道的道路如下图所示:

需要修建  条赛道。可以修建如下  条赛道:

  1. 经过第  条道路的赛道(从路口  到路口 ),长度为 ;
  2. 经过第  条道路的赛道(从路口  到路口 ),长度为 ;
  3. 经过第  条道路的赛道(从路口  到路口 ),长度为 。

长度最小的赛道长度为 ,为所有方案中的最大值。

数据规模与约定

这数据真好看,不是,这姑娘真良心

所有测试数据的范围和特点如下表所示 :

其中,「分支不超过 33」的含义为:每个路口至多有 3 条道路与其相连。

对于所有的数据,2≤n≤5×10000, 1≤m≤n−1, 1≤ai​,bi​≤n, 1≤li​≤10000

关于 multiset参考于(https://blog.csdn.net/sodacoco/article/details/84798621)         ----          二喵君

与(https://blog.csdn.net/qq_40032278/article/details/81511494 )     --------------          L--辰缘--H

解题思路:

最大值最小,好,我们直接想到了二分,二分什么呢?——困扰了我整整40多分钟(我当时就剩下40分钟了,~~~~(>_<)~~~~)

要求 m  条赛道中长度最小的赛道长度最大,所以我们二分就是赛道的长度,我们要求的就是最小的赛道,,,,,,然后长度最大

所以,题意就化成了 在一棵树上能否找出小于等于 k 的 m 条路径;(为了加深我的理解,毕竟刚理解,写的多一点)

在分路径的时候,也用到了贪心;就是如果现在形成的长度不足k,那我们去寻找路径的时候,去寻找最小的且没被选过的路径,以此来保证我们所分得的路径最多,用的就是multiset;

考虑一棵子树对全局答案的贡献,显然有两个方面。

  1. 是当前子树中能最多能找到的满足要求的路径条数;
  2. 是连到当前子树的根的路径的长度​。

这样也就可以求树的直径,不求树的直径也就是慢了300ms左右吧

然后,客官,上代码吧:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
const int maxn=50000+120;
struct node
{
int nxt ,to,weath;
}edge[maxn<<1];
multiset<int> s[maxn];
multiset<int>::iterator it;
int dist,n,m,up;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int number_edge,head[maxn<<1];
void add_edge(int from,int to,int weath)
{
number_edge++;
edge[number_edge].nxt=head[from];
edge[number_edge].to=to;
edge[number_edge].weath=weath;
head[from]=number_edge;
}
int dfs1(int x,int fa
{
int sum1=0;
int sum2=0;
for(int i=head[x];i;i=edge[i].nxt)
{
if(edge[i].to==fa)
{
continue;
}
sum2=max(sum2,dfs1(edge[i].to,x)+edge[i].weath);
if(sum1<sum2)
{
swap(sum1,sum2);
}
}
up=max(up,sum1+sum2);
return sum1;
}
int dfs(int x,int fa,int k)
{
s[x].clear();
int val;
for(int i=head[x];i;i=edge[i].nxt)
{
if(edge[i].to==fa)
{
continue;
}
val=dfs(edge[i].to,x,k)+edge[i].weath;
if(val>=k)
{
dist++;
}
else
{
s[x].insert(val);
}
}
int Max=0;
while(!s[x].empty())
{
if(s[x].size()==1)
{
return max(Max,*s[x].begin());
}
it=s[x].lower_bound(k-*s[x].begin());
if(it==s[x].begin()&&s[x].count(*it)==1)
{
it++;
}
if(it==s[x].end())
{
Max=max(Max,*s[x].begin());
s[x].erase(s[x].find(*s[x].begin()));
}
else
{
dist++;
s[x].erase(s[x].find(*it));
s[x].erase(s[x].find(*s[x].begin()));
}
}
return Max;
}
bool check(int k)
{
dist=0;
dfs(1,0,k);
return dist>=m;
}
int main()
{ n=read(),m=read();
int ans;
for(int i=1;i<=n-1;i++)
{
int x=read(),y=read(),w=read();
add_edge(x,y,w);
add_edge(y,x,w);
}
dfs1(1,0);
int l=1,r=100000;
while(l<r)
{
int mid=l+r+1>>1;
if(check(mid))
{ l=mid;
ans=l;
}
else
{
r=mid-1;
}
}
printf("%d\n",ans);
return 0;
}

OK,综上所述,今天学到了着实不少~~To be continue;

NOIP 2018 D1 解题报告(Day_1)的更多相关文章

  1. 【NOIP2015】提高组D1 解题报告

    P1978神奇的幻方 Accepted 描述 幻方是一种很神奇的 N ∗ N 矩阵:它由数字 1,2,3, … … , N ∗ N 构成,且每行.每列及两条对角线上的数字之和都相同. 当 N 为奇数时 ...

  2. 2018.10.16 NOIP模拟赛解题报告

    心路历程 预计得分:\(100 + 100 + 20 = 220\) 实际得分:\(100 + 100 + 30 = 230\) 辣鸡模拟赛.. T1T2都是一眼题,T3考验卡常数还只有一档暴力分. ...

  3. 2018.10.03 NOIP+ 模拟赛 解题报告

    得分: \(30+5+0=35\)(考得真不咋滴) \(T1\):奥义商店(点此看题面) 以为很简单,对着这题想了一个多小时,最后果断打了个暴力交了... ... 看完题解发现其实也不是很难. 对于\ ...

  4. 9月24日noip模拟赛解题报告

    1.校门外的树(tree.c/cpp/pas 128M,1s) Description LSGJ扩建了,于是校门外有了一条长为L的路.路上种了一排的树,每相邻两棵树之间的距离为1,我们可以把马路看成一 ...

  5. NOIP 2017 Day1 解题报告

    总分:100分 T1,小凯的疑惑, 100分 T2,时间复杂度,0分 T3,逛公园,0分 T1 ###题意简化: 给定两个互质的数字,输出最大不能表示的数: 基础数论题目 代码: #include&l ...

  6. 20161022 NOIP模拟赛 解题报告

     好元素 [问题描述] 小A一直认为,如果在一个由N个整数组成的数列{An}中,存在以下情况: Am+An+Ap = Ai (1 <= m, n, p < i <= N ,  m,n ...

  7. 2018-11-1 NOIP 模拟赛解题报告

    T1 Domino 多米诺骨牌 题目大意 给你N个骨牌,上下各有一个数,要使上面一排的和为偶数,同时下面一排的和也为偶数,最多要翻转多少次?如果无法达成那么输出-1. 解法 水题秒切 根据数的奇偶性质 ...

  8. 2015-9-13 NOIP模拟赛解题报告(by hzwer)

    小奇挖矿 「题目背景」 小奇要开采一些矿物,它驾驶着一台带有钻头(初始能力值w)的飞船,按既定路线依次飞过喵星系的n个星球. 「问题描述」 星球分为2类:资源型和维修型. 1.资源型:含矿物质量a[i ...

  9. [JXOI 2018] 守卫 解题报告 (DP)

    interlinkage: https://www.luogu.org/problemnew/show/P4563 description: solution: 注意到对于范围$[l,r]$,$r$这 ...

随机推荐

  1. 重拾H5小游戏之入门篇(二)

    上一篇,水了近千字,很酸爽,同时表达了"重拾"一项旧本领并不容易,还有点题之效果.其实压缩起来就一句话:经过了一番记忆搜索,以及try..catch的尝试后,终于选定了Phaser ...

  2. Layman 分享到朋友圈或发送给朋友

    *主要是介绍如何在网页中实现发送给朋友和分享到朋友圈时内容参数自定义的功能 微信JS接口 1.微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包; 通过使用微信JS-SDK, ...

  3. Sprign-mvc系列之Spring快速入门 什么是sprign-mvc spring-mvc的作用及其基本使用+组件解析+注解解析

    Spring-mvc 什么是SpringMvc SpringMvc是一种基于java的实现Mvc设计模式的请求驱动类型的轻量级web框架,属于SpringFrameWork的后续产品,已经融合在Spr ...

  4. 利用 yum 命令和 rpm 命令升级 Nginx 或者安装最新版本 Nginx

    方法一:使用 yum 命令升级 Nginx 1.在配置 YUM 仓库的目录(/etc/yum.repos.d/)下新增文件  nginx.repo vi /etc/yum.repos.d/nginx. ...

  5. 多台centos7服务器实现SSH免密登陆

    一.环境 centos7.x 三台 node1.node2.node3 二.实现免密登陆 2.1.node1上,生成公钥与私钥 [root@node1 ~]# ssh-keygen Generatin ...

  6. Python+Appium自动化测试(15)-使用Android模拟器(详细)

    做APP的UI自动化测试时,我们往往会使用真机跑自动化测试脚本,因为这样才是最真实的使用场景.但前期调试脚本的话,可以先使用模拟器,这样相对更加方便. 不推荐使用Android SDK里自带模拟器,太 ...

  7. Brew error: Could not symlink, path is not writable

    As explained here by Rick: Start with brew doctor which will show you errors with your brew setup. Y ...

  8. 多测师_肖sir _python 练习题(一)100以内奇数,偶数,质数胡计算

    (1)求1~100的和方法: 方法一:print(sum(range(1,101))) 方法二: sum1 = 0 i = 1 while True: sum1 = sum1 + i if i == ...

  9. Rust之路(3)——数据类型 下篇

    [未经书面同意,严禁转载] -- 2020-10-14 -- 架构是道,数据是术.道可道,非常道:术不名,不成术!道无常形,术却可循规. 学习与分析数据类型,最基本的方法就是搞清楚其存储原理,变量和对 ...

  10. 解决加密PDF文档无法复制文字的问题

    有的时候在网络上搜索到一篇心仪的PDF文档,想复制其中内容时提示无法复制. 如果只想摘抄其中部分文字内容,可以使用Firefox浏览器打开这篇加密文档. Firefox浏览器自带PDF插件,打开后即可 ...