HGOI20191115 模拟赛 题解
Problem A 表演
有$n$个有点权的点,$m$个有边权的边。对于每个点$u$,输出从这个点出发到$v$,其路径权值的两倍加上v的点权和最小的值。
对于$100\%$的数据,满足$1 \leq n,m \leq 2\times 10^5 $
Solution :
考虑一个简单的转移,$f[u]$表示点$u$的最小答案,最初$f[u]$ 为$u$的点权。
每一次更新,就是相邻的两个点$u,v$之间,用边权的两倍来更新答案。
如果在图上DP,那么就相当于,将初始这些点权加入priority_queue,跑最短路即可。
时间复杂度为$O(m log_2 n)$
# include <bits/stdc++.h> # define int long long using namespace std; const int N=2e5+10; struct rec{ int pre,to,w;}a[N<<1]; int n,m,tot; bool inq[N]; int head[N],d[N],val[N]; namespace Fast_IO { inline int read() { int x=0,w=0; char c=0; while (c<'0'||c>'9') w|=c=='-',c=getchar(); while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return w?-x:x; } void write(int x) { if (x<0) x=-x,putchar('-'); if (x>9) write(x/10); putchar('0'+x%10); } void writeln(int x) { write(x); putchar('\n'); } }; using namespace Fast_IO; void adde(int u,int v,int w) { a[++tot].pre=head[u]; a[tot].to=v; a[tot].w=w*2; head[u]=tot; } struct Node { int id,val; }; struct cmp { bool operator () (Node a,Node b) { return a.val > b.val; } }; priority_queue<Node,vector<Node>,cmp>q; void dijkstra() { for (int i=1;i<=n;i++) { d[i]=val[i]; inq[i]=true; q.push((Node){i,val[i]}); } while (q.size()) { int u=q.top().id; q.pop(); inq[u]=false; for (int i=head[u];i;i=a[i].pre) { int v=a[i].to; if (d[v]>d[u]+a[i].w) { d[v]=d[u]+a[i].w; if (!inq[v]) q.push((Node){v,d[v]}); } } } } signed main() { n=read();m=read(); for (int i=1;i<=m;i++) { int u=read(),v=read(),w=read(); adde(u,v,w); adde(v,u,w); } for (int i=1;i<=n;i++) val[i]=read(); dijkstra(); for (int i=1;i<n;i++) write(d[i]),putchar(' '); writeln(d[n]); return 0; }
Problem B 逮虾户
要求的车速是一个大于等于0的值,设第$i$次估计的车速为$v_i$,走的路程为$s_i$,
设$v'$表示真实速度,则有偏差值$d$的定义式为 $d = v' - v_i$。
考虑对速度的估计的偏差值d每一次都恒定。
给出$n$次测算的结果$s_i , v_i$,和这几次测试总共的用时$t$,输出$d$的值。
对于$100\%$的数据满足$1 \leq n\leq 10^3,1 \leq s_i \leq 10^3 , |v_i| \leq 10^3$
Solution :
考虑$t$这个函数是在$n+1$段不连续的定义域中单调减的。
所以,我们可以做$n+1$二分,就能找到些定义域中和d最相近的。
、 注意,最后统计答案的时候,需要check一下实际车速大于等于0.
时间复杂度为$O(n ^2 log_2 S)$,其中$S$表示确定实数域大小。
# include <bits/stdc++.h> using namespace std; const int N=1e3+10; const double eps = 1e-9; struct rec{double s,v;}a[N]; int n,t; vector<double>ans; bool cmp (rec x, rec y) { return x.v>y.v; } double f (double x) { double res = 0; for (int i=1;i<=n;i++) res += (double)a[i].s/(double)(x+a[i].v); return res; } double work(double l,double r) { while (fabs(r-l)>=eps) { double mid = (l+r)/2.0; if (f(mid)<=t) r=mid; else l=mid; } return l; } double calc(double x) { return fabs(f(x)-t); } int main() { scanf("%d%d",&n,&t); for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].s,&a[i].v); sort(a+1,a+1+n,cmp); double l=-1e9; for (int i=1;i<=n;i++) { ans.push_back(work(l,-a[i].v-eps)); l=-a[i].v+eps; } ans.push_back(work(l,1e9)); double res = ans[0], delta =calc(ans[0]); for (int i=1;i<ans.size();i++) { bool ok = true; for (int j=1;j<=n;j++) if (a[j].v+ans[i]<eps) { ok = false; break; } if (!ok) continue; double tmp = calc(ans[i]); if (tmp <= delta) { res = ans[i]; delta = tmp; } } printf("%.10lf\n",res); return 0; }
Problem C 跳一跳
如果序列中任意相邻两个元素,都是极值点,其中一个是极大值点,另外一个极小值点。
那么这个序列叫做波浪序列。
给出对于长度为$n$序列,输出最长波浪序列的长度。
对于$100\%$的数据满足 $1 \leq n \leq 10^5 , 1 \leq a_i \leq 10^9 $
Solution :
由于元素只进行比较,所以我们可以将其离散化。
设$f[i][0]$表示第$i$个元素作为极小点为结尾的最长波浪序列长度,$f[i][1]$表示第$i$个元素作为极大点为结尾的最长波浪序列长度。
转移方程为:$f[i][0] = max(f[j][1] + 1) (a_i < a_j) , f[i][1] = max (f[j][0] + 1) (a_i > a_j)$
可以用值域线段树来维护这个$DP$。时间复杂度为$O(n log_2 n)$
# include <bits/stdc++.h> using namespace std; const int N=1e5+10; int a[N],n,f[N][2]; vector<int>tmp; namespace Fast_IO { inline int read() { int x=0,w=0; char c=0; while (c<'0'||c>'9') w|=c=='-',c=getchar(); while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return w?-x:x; } void write(int x) { if (x<0) x=-x,putchar('-'); if (x>9) write(x/10); putchar('0'+x%10); } void writeln(int x) { write(x); putchar('\n'); } }; using namespace Fast_IO; struct Segment_Tree { int tr[N<<2]; # define ls (x<<1) # define rs (x<<1|1) # define mid (l+r>>1) # define lson ls,l,mid # define rson rs,mid+1,r void update(int x,int l,int r,int pos,int opx) { if (l==r) { tr[x]=max(tr[x],opx); return; } if (pos<=mid) update(lson,pos,opx); else update(rson,pos,opx); tr[x]=max(tr[ls],tr[rs]); } int query(int x,int l,int r,int opl,int opr) { if (opl<=l && r<=opr) return tr[x]; int ret=0; if (opl<=mid) ret=max(ret,query(lson,opl,opr)); if (opr>mid) ret=max(ret,query(rson,opl,opr)); return ret; } }tr0,tr1; int main() { n=read(); for (int i=1;i<=n;i++) { tmp.push_back(a[i]=read()); } sort(tmp.begin(),tmp.end()); tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end()); int m = tmp.size(); for (int i=1;i<=n;i++) { a[i]=lower_bound(tmp.begin(),tmp.end(),a[i])-tmp.begin()+1; } int ans = 0; for (int i=1;i<=n;i++) { f[i][0]=f[i][1]=1; if (a[i]-1>=1) f[i][1] = max(f[i][1],tr0.query(1,1,m,1,a[i]-1)+1); if (a[i]+1<=m) f[i][0] = max(f[i][0],tr1.query(1,1,m,a[i]+1,m)+1); ans = max(ans,max(f[i][0],f[i][1])); tr0.update(1,1,m,a[i],f[i][0]); tr1.update(1,1,m,a[i],f[i][1]); } writeln(ans); return 0; }
原文地址:https://www.cnblogs.com/ljc20020730/p/11866620.html
- 在Python机器学习中如何索引、切片和重塑NumPy数组
- HelloWorld,我的第一趟旅程出发点
- Android OpenGL开发实践 - GLSurfaceView对摄像头数据的再处理
- 走进科学:对七夕“超级病毒”XX神器的逆向分析
- 机器学习 - 朴素贝叶斯分类器的意见和文本挖掘
- 认知指纹:颠覆性的身份认证技术
- 跟我学姿势:极客教你如何科学的看电影
- Discuz 5.x/6.x/7.x投票SQL注入分析
- 论如何高效的挖掘漏洞
- Rxjava + retrofit + dagger2 + mvp搭建Android框架
- 走进科学:如何正确的隐藏自己的行踪
- 比特儿(Bter.com) 比特币交易平台被盗事件全解析
- BitTorrent Bleep:无法被监控的聊天软件
- QQ蠕虫的行为检测方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 曾经绊倒我的 “超级丑数”
- Flutter 完成全平台制霸:实现 Windows 应用支持
- 尤大 4 天前发在 GitHub 上的 vue-lit 是啥?
- 原创的20个Python自动化案例,一口一个,高效办公!
- 看完这篇Python操作PPT总结,从此使用Python玩转Office全家桶就没有压力了!
- 【Hadoop 分布式部署 三:基于Hadoop 2.x 伪分布式部署进行修改配置文件】
- DCL单例模式你不知道的秘密
- 《大话数据结构》队列的顺序存储和链式存储
- 《大话数据结构》栈的顺序存储及链式存储
- 《大话数据结构》之双向链表
- 《大话数据结构》线性表的链式存储结构
- 《大话数据结构》线性表的顺序存储结构
- 《啊哈算法》桶排序详解
- 你不得不知道的Git常用命令
- Java中静态代码块、代码块以及构造函数执行顺序详解