前言

关于\(NOIP2018\),详见此博客:NOIP2018学军中学游记(11.09~11.11)。

这次\(NOIP\ Day1\)的题目听说很简单(毕竟是三道原题),然而我\(T3\)依然悲剧地写炸了。

很奇怪啊,毕竟在几乎所有民间数据中我这题都\(AC\)了... ...

\(T1\):铺设道路(点此看题面)

另一个题面

我的思路是,每个元素肯定都是由其左右两边第一个比它小的数转移而来的。

于是就开了两个单调栈,前后各扫一遍,求出了答案。

然而貌似还有更简单的解法?但我不会。

代码如下:

#include<bits/stdc++.h>
#define N 100000
using namespace std;
int n,a[N+5],s[N+5],Stack[N+5];
int main()
{register int i,ans=0,Top=0;for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&a[i]);for(i=1;i<=n;++i)//从前往后,求出第一个小于等于a[i]的数{while(Top&&Stack[Top]>=a[i]) --Top;//单调栈s[i]=a[i]-Stack[Top],Stack[++Top]=a[i];//将a[i]-Stack[Top]存储下来,然后将a[i]加入栈}for(Top=0,i=n;i;--i)//从后往前,求出第一个小于a[i]的数{while(Top&&Stack[Top]>a[i]) --Top;//单调栈,注意前面加了=,这题就不能加了,否则会重复计算ans+=min(s[i],a[i]-Stack[Top]),Stack[++Top]=a[i];//统计答案}return printf("%d",ans),0;
}

\(T2\):货币系统(点此看题面)

比较裸的完全背包但是我不会。

我的思路就是先\(sort\)一遍,然后暴力更新每种价值是否能由之前的价值组合而成。

这样显然会\(TLE\)。

于是我又考虑再用一个\(lst\)数组存储每种价值上一次是被价值为多少的元素更新的,如果上次就是由当前元素更新的,则可直接\(break\)。

这样一优化就\(AC\)了(实际上加上这个优化之后与完全背包应该是等价的)。

代码如下:

#include<bits/stdc++.h>
#define N 100
#define P 25000
using namespace std;
inline void Gmax(int &x,int y) {x<y&&(x=y);}
int n,a[N+5],vis[P+5],lst[P+5];
int main()
{register int T,i,j,k,ans,Max;for(scanf("%d",&T);T;--T){for(scanf("%d",&n),ans=n,Max=0,i=1;i<=n;++i) scanf("%d",&a[i]),Gmax(Max,a[i]);//求最大值for(vis[0]=T,sort(a+1,a+n+1),i=1;i<=n;++i)//现将a[i]排序一遍,并标记价值0已被访问{if(vis[a[i]]^T)//如果当前的价值不可以被之前的价值组合而成{for(j=Max;~j;--j)//枚举值 {if(vis[j]^T) continue;//如果当前值不能被之前的价值组合而成,跳过for(k=1;1LL*a[i]*k+j<=Max;++k)//更新{if(vis[a[i]*k+j]^T||lst[a[i]*k+j]^a[i]) vis[a[i]*k+j]=T,lst[a[i]*k+j]=a[i];//如果没访问过,或不是由当前价值的元素更新的,更新其vis数组和lst数组else break;//否则,可以直接退出循环}}}else --ans;//如果可以组合而成,将ans减1}printf("%d\n",ans);}
}

\(T3\):赛道修建(点此看题面)

这题有很多做法,我个人认为还是二分+\(multiset\)比较好写。

首先,先二分答案\(ans\)。(关于二分的上界,可以设置为树的直径

关于如何验证,我们可以考虑用一个变量\(tot\)存储满足条件的路径数,并对树上每一个节点开一个\(multiset\)。

对于当前节点\(x\),设其有\(Size\)个子节点,由于每条边只能选择一次,则最多只有\(Size\)条从子节点到其的路径会被选择。

而这些路径可能有长度大于等于\(ans\)的,对于这样的边,直接将\(tot\)加\(1\)即可,否则,可以将其扔入\(multiset\)。

比较显然,我们可以开一个变量\(res\)来存储没有被选择的边中最长边的长度。然后从小到大枚举剩下的路径,每次找到与其和大于等于\(ans\)的最短边,并将它们同时删除,然后将\(tot\)加\(1\)。如果找不到,就更新\(res\)。

最后返回\(res\),就是最后选择的通向父节点的路径。

代码如下:

#include<bits/stdc++.h>
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define Gmin(x,y) (x>(y)&&(x=(y)))
#define N 50000
#define add(x,y,v) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].val=v)
using namespace std;
int n,m,ee,lnk[N+5];
struct edge
{int to,nxt,val,used;
}e[(N<<1)+5];
class Class_FIO
{private:#define Fsize 100000#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,Fsize,stdin),A==B)?EOF:*A++)#define pc(ch) (void)(FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,Fsize,stdout),Fout[(FoutSize=0)++]=ch))int Top,FoutSize;char ch,*A,*B,Fin[Fsize],Fout[Fsize],Stack[Fsize];public:Class_FIO() {A=B=Fin;}inline void read(int &x) {x=0;while(!isdigit(ch=tc()));while(x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));}inline void write(int x) {if(!x) return pc('0');while(x) Stack[++Top]=x%10+48,x/=10;while(Top) pc(Stack[Top--]);}inline void clear() {fwrite(Fout,1,FoutSize,stdout),FoutSize=0;}
}F;
class Class_TreeDiameterSolver//求树的直径,实际上可以直接用BFS,但我用了树形DP
{private:int ans,Max[N+5],Max_[N+5],MaxSon[N+5];inline void dfs1(int x,int lst){register int i;for(Max[x]=Max_[x]=MaxSon[x]=0,i=lnk[x];i;i=e[i].nxt){if(!(e[i].to^lst)) continue;dfs1(e[i].to,x);if(Max[e[i].to]+e[i].val>Max[x]) Max_[x]=Max[x],Max[x]=Max[MaxSon[x]=e[i].to]+e[i].val;else if(Max[e[i].to]+e[i].val>Max_[x]) Max_[x]=Max[e[i].to]+e[i].val;}Gmax(ans,Max[x]+Max_[x]);}inline void dfs2(int x,int lst,int val){register int i;for(i=lnk[x];i;i=e[i].nxt){if(!(e[i].to^lst)) continue;dfs2(e[i].to,x,max(val,e[i].to^MaxSon[x]?Max[x]:Max_[x])+e[i].val);}Gmax(ans,Max[x]+val);}public:inline int GetAns() {return dfs1(1,0),dfs2(1,0,0),ans;}
}TD;
class Class_Checker//验证答案
{private:int tot;multiset<int> s[N+5];multiset<int>::iterator p;inline int dfs(int x,int lst,int val)//遍历树,x表示当前访问到的节点,lst表示父节点,val表示当前验证的答案{register int i,t,res=0;//res存储没有被选择边中最长边的长度for(s[x].clear(),i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&((t=dfs(e[i].to,x,val)+e[i].val)>=val?++tot:(s[x].insert(t),0));//枚举子节点,如果当前边长度大于等于val,则将tot加1,否则将其扔入multisetwhile(!s[x].empty())//如果multiset不为空{if(t=*s[x].begin(),!(s[x].size()^1)) return max(res,t);//如果只剩一条边,返回res与当前边长度的较大值(p=s[x].lower_bound(val-t))==s[x].begin()&&!(s[x].count(t)^1)&&(++p,0),(p==s[x].end()?Gmax(res,t):(s[x].erase(p),++tot)),s[x].erase(s[x].begin());//找到与其和大于等于ans的最短边,并将它们同时删除,然后将tot加1。如果找不到,就更新res}return res;//返回res}public:inline bool Check(int val) {return tot=0,dfs(1,0,val),tot>=m;}//判断tot是否大于等于m
}C;
int main()
{register int i,x,y,v,l,r,mid;for(F.read(n),F.read(m),i=1;i<n;++i) F.read(x),F.read(y),F.read(v),add(x,y,v),add(y,x,v);for(mid=(l=0)+(r=TD.GetAns())+1>>1;l<r;mid=l+r+1>>1) C.Check(mid)?l=mid:r=mid-1;//二分答案return F.write(l),F.clear(),0;
}

转载于:https://www.cnblogs.com/chenxiaoran666/p/NOIP2018Day1.html

NOIP2018提高组Day1 解题报告相关推荐

  1. NOIP2013 提高组复赛解题报告

    NOIP2013 提高组复赛 day1 day\;1 1002. 火柴排队 贪心+数据结构/归并排序 这个"相邻交换"让我联想到了NOIP2012_day1_task2_game那 ...

  2. NOIP2016提高组复赛解题报告

    Day1 T1-玩具谜题 Day1 T2-天天爱跑步 Day1 T3-换教室 Day2 T1-组合数问题 Day2 T2-蚯蚓 Day2 T3-愤怒的小鸟 转载于:https://www.cnblog ...

  3. NOIP2018提高组比赛总结

    NOIP2018提高组比赛总结 前言 新赛季,依旧有很多失误. 在些许的遗憾和无奈中,NOIP2018,撒花结束 纵观今年的整一场NOIP,有许多值得总结的地方 正文 NOIP2018初赛 第二次参加 ...

  4. NOIP2018提高组心路历程(AFO+自闭)

    NOIP2018提高组历程(AFO+自闭) 在不断地考试考试考试(浪浪浪)中,不知不觉,11月9号这个出征日就到来了,再出发前还是有很多小插曲的(比如刚好正面遇到她,吃好饭后还对视了一眼).随着大巴的 ...

  5. P5049 [NOIP2018 提高组] 旅行

    P5049 [NOIP2018 提高组] 旅行 题意: 一棵树(可能是基环树),从1出发,每到达一个新的点就记录下编号.求一种走法使得记录下来的编号字典序最小. 1≤n≤500000 m=n−1 或 ...

  6. 51Nod NOIP2018提高组省一冲奖班模测训练

    51Nod NOIP2018提高组省一冲奖班模测训练 NOIP2018提高组省一冲奖班模测训练1 T1 珂朵莉的旅行 T2 奈芙莲的序列 T3 奈芙莲的护符 NOIP2018提高组省一冲奖班模测训练2 ...

  7. 学大伟业Day1解题报告

    学大伟业Day1解题报告 张炳琪 一.   时间分配 T1:30分钟  T2: 60分钟  T3:100分钟 二.答题情况及错因 T1:100         T2:55             T3 ...

  8. NOIP2018提高组省一冲奖班模测训练(三)

    NOIP2018提高组省一冲奖班模测训练(三) 自己按照noip的方式考,只在最后一两分钟交了一次 第一题过了,对拍拍到尾. 第二题不会.考试时往组合计数的方向想,推公式,推了一个多小时,大脑爆炸,还 ...

  9. NOIP2018提高组省一冲奖班模测训练2 T3 XYK的音游

    10月22日NOIP2018提高组省一冲奖班模测训练2 T3 XYK的音游 题目描述 XYK最近入坑了一个新音游. 游戏界面上有Ñ个并排的按键,当前这首歌有米个鼓点.游戏的玩法是在鼓点的时刻移动鼠标到 ...

最新文章

  1. npm i和npm install的区别
  2. LoadRunner 技巧之 手动关联与预关联
  3. matlab中rand函数使用
  4. R语言基于线性回归(Linear Regression)进行特征筛选(feature selection)
  5. 软件测试2019:第七次作业—— 用户体验测试
  6. 公积金联名卡——提取公积金用,用身份证即可办理
  7. golang中的可见性
  8. javascript标签在页面中的位置探讨
  9. Kettle能做什么?
  10. ssl1500-最短路上的统计【Floyd】
  11. Java小白进阶笔记(3)-初级面向对象
  12. Nginx 负载均衡策略之加权轮询分析
  13. mysql5.7.11源码安装,mysql 5.7.11 源码安装
  14. Java 核心内容相关面试题【2】
  15. 英文语音识别_英文语音识别软件_英文语音识别翻译 - 云+社区 - 腾讯云
  16. Windows添加启动项的两种方法
  17. HDOJ--1864--最大报销额
  18. 点石成金 访客至上的Web和移动可用性设计秘笈pdf
  19. 本科毕业论文查重网站分享(维普、知网、万方、大雅等)
  20. python基础(16):学生信息管理系统——Python编写(附全部代码)

热门文章

  1. 网络通信常见加密剖析
  2. JasperReport 打印面单时遇到的坑
  3. idea打包war包,将自己的项目打包为war包
  4. 威联通TS-532x 篇零 qts5.0不插盘不能运行,不能安装系统
  5. 如何有效治理线上假货
  6. NREC-手动修改直纹面,可线铣编程
  7. 小 C 的数学(math)
  8. redis 04:Redis高可用集群
  9. 【愚公系列】2022年02月 攻防世界-进阶题-MISC-85(Disk)
  10. 如何在beamer中添加分栏的内容