2021.7.15考试总结[NOIP模拟16]
ZJ模拟D2就是NB。。
T1 Star Way To Heaven
谁能想到这竟是个最小生成树呢?(T1挂分100的高人JYF就在我身边
把上边界和下边界看成一个点和星星跑最小生成树,从上边界开始跑到下边界,一定会出现一条将矩阵纵向一分为二的折线,其中线段都是最小距离,答案就是其中最长的线段的一半。
我直呼NB
由于这是个完全图,kruscal比prim多个log,会炸。
code:

1 #include<bits/stdc++.h>
2 #define debug exit(0)
3 using namespace std;
4 const double eps=1e-8;
5 const int NN=6e3+5;
6 int n,m,k,nod;
7 double ans,dis[NN],x[NN],y[NN];
8 bool vis[NN];
9 inline int read(){
10 int x=0,f=1;
11 char ch=getchar();
12 while(ch<'0'||ch>'9'){
13 if(ch=='-') f=-1;
14 ch=getchar();
15 }
16 while(ch>='0'&&ch<='9'){
17 x=(x<<1)+(x<<3)+(ch^48);
18 ch=getchar();
19 }
20 return x*f;
21 }
22 double ds(int a,int b){
23 return sqrt(1.0*(x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));
24 }
25 int main(){
26 n=read(); m=read(); k=read();
27 for(int i=1;i<=k;i++)
28 x[i]=read(), y[i]=read();
29 for(int i=1;i<=k;i++)
30 dis[i]=m-y[i];
31 dis[k+1]=m; dis[0]=1e9;
32 while(1){
33 int to=0;
34 for(int i=1;i<=k+1;i++)
35 if(!vis[i]&&dis[i]<dis[to]) to=i;
36 ans=max(ans,dis[to]); vis[to]=1;
37 if(to==k+1){
38 printf("%.8lf\n",ans/2);
39 return 0;
40 }
41 for(int i=1;i<=k;i++)
42 dis[i]=min(dis[i],ds(i,to));
43 dis[k+1]=min(dis[k+1],1.0*y[to]);
44 }
45 }
T1
T2 God Knows
用B哥的话说,第一眼DP,第二眼不会。
看这题满脑子状压,但数据范围无情地把我拉回现实。
又想了一会树规,但假了。无奈之下,还是不想打状压,一调一小时于是果断糊了个DFS拿了20。
正解是个NB东西。把p看作带权序列,问题转化成求最小权极长上升子序列。

n2无法过掉,考虑神仙优化。如何优化呢?
万能的线段树!
发现能更新dpi的j满足它的p是从j到i中所有小于pi的最大值,但仍难以维护。
于是可以在线段树中维护以p为下标,i为关键值的一个单调栈。那么又到了我不懂的东西。
在每个节点上维护一个单调栈,记录栈底元素(i最大值),其中最小的权值(即为dp数组),和左儿子被右儿子最大值更新后的最小权值。
写一个cal函数计算当前节点的栈中加入关键值为val的元素后的最小权值。
用一个nxt计接下来要向栈中压进的元素,因为要把右儿子栈底压进左边,每次查询先询问右边来得到接下来询问范围。
code:

1 #include<bits/stdc++.h>
2 #define ld rt<<1
3 #define rd (rt<<1)|1
4 #define debug exit(0)
5 using namespace std;
6 const int NN=2e5+5,inf=2e9;
7 int n,p[NN],c[NN],nxt;
8 inline int Min(int a,int b){ return a<b?a:b; }
9 inline int Max(int a,int b){ return a<b?b:a; }
10 inline int read(){
11 int x=0,f=1;
12 char ch=getchar();
13 while(ch<'0'||ch>'9'){
14 if(ch=='-') f=-1;
15 ch=getchar();
16 }
17 while(ch>='0'&&ch<='9'){
18 x=(x<<1)+(x<<3)+(ch^48);
19 ch=getchar();
20 }
21 return x*f;
22 }
23 void write(int x){
24 if(x<0) putchar('-'), x=-x;
25 if(x>9) write(x/10);
26 putchar(x%10+'0');
27 }
28 struct segment_tree{
29 int l[NN<<2],r[NN<<2],mn[NN<<2],um[NN<<2],mx[NN<<2];
30 int cal(int rt,int val){
31 if(l[rt]==r[rt]) return mx[rt]>val?mn[rt]:inf;
32 if(mx[rd]>val) return Min(um[ld],cal(rd,val));
33 return cal(ld,val);
34 }
35 void pushup(int rt){
36 mx[rt]=Max(mx[ld],mx[rd]);
37 mn[rt]=Min(mn[rd],um[ld]=cal(ld,mx[rd]));
38 }
39 void build(int rt,int opl,int opr){
40 l[rt]=opl; r[rt]=opr;
41 mn[rt]=um[rt]=inf; mx[rt]=-1;
42 if(opl==opr) return;
43 int mid=opl+opr>>1;
44 build(ld,opl,mid); build(rd,mid+1,opr);
45 }
46 int query(int rt,int opl,int opr){
47 if(l[rt]>=opl&&r[rt]<=opr){
48 int ans=cal(rt,nxt);
49 nxt=Max(nxt,mx[rt]);
50 return ans;
51 }
52 int mid=l[rt]+r[rt]>>1,ans=inf;
53 if(opr>mid) ans=Min(ans,query(rd,opl,opr));
54 if(opl<=mid) ans=Min(ans,query(ld,opl,opr));
55 return ans;
56 }
57 void insert(int rt,int pos,int i,int val){
58 if(l[rt]==r[rt]){ mn[rt]=val; mx[rt]=i; return; }
59 int mid=l[rt]+r[rt]>>1;
60 if(pos<=mid) insert(ld,pos,i,val);
61 else insert(rd,pos,i,val);
62 pushup(rt);
63 }
64 }s;
65 int main(){
66 n=read();
67 for(int i=1;i<=n;i++) p[i]=read();
68 for(int i=1;i<=n;i++) c[i]=read();
69 ++n; p[n]=n; s.build(1,0,n); s.insert(1,0,0,0);
70 for(int i=1;i<=n;i++){
71 nxt=-1;
72 int tmp=s.query(1,0,p[i]-1)+c[i];
73 s.insert(1,p[i],i,tmp);
74 if(i==n) write(tmp), putchar('\n');
75 }
76 return 0;
77 }
T2
T3 Lost My Music
一看就是个斜率,但我没学
用单调栈(可持久化)维护一个下凸包,每次求凸包切线。
暴力弹栈会炸,于是学着用了个倍增。代码挺短
贴个斜率优化博客
code:

1 #include<bits/stdc++.h>
2 #define debug exit(0)
3 using namespace std;
4 const double eps=1e-8;
5 const int NN=5e5+5;
6 int n,fa[NN][21],to[NN],nex[NN],head[NN],num,dep[NN],ans[NN],c[NN];
7 inline int read(){
8 int x=0,f=1;
9 char ch=getchar();
10 while(ch<'0'||ch>'9'){
11 if(ch=='-') f=-1;
12 ch=getchar();
13 }
14 while(ch>='0'&&ch<='9'){
15 x=(x<<1)+(x<<3)+(ch^48);
16 ch=getchar();
17 }
18 return x*f;
19 }
20 inline void add(int a,int b){
21 to[++num]=b; nex[num]=head[a]; head[a]=num;
22 }
23 inline double Min(double a,double b){
24 return a<b?a:b;
25 }
26 inline double calc(int x,int y){
27 return 1.0*(c[y]-c[x])/(dep[x]-dep[y]);
28 }
29 void dfs(int st){
30 int father=fa[st][0];
31 for(int i=19;i>=0;i--){
32 if(fa[father][i]<2) continue;
33 if(calc(st,fa[father][i])>=calc(st,fa[fa[father][i]][0])) father=fa[father][i];
34 }
35 if(calc(st,father)>=calc(st,fa[father][0])&&father>1) father=fa[father][0];
36 ans[st]=fa[st][0]=father;
37 for(int i=1;i<=19;i++)
38 fa[st][i]=fa[fa[st][i-1]][i-1];
39 for(int i=head[st];i;i=nex[i]){
40 dep[to[i]]=dep[st]+1;
41 dfs(to[i]);
42 }
43 }
44 int main(){
45 n=read();
46 for(int i=1;i<=n;i++) c[i]=read();
47 for(int i=2;i<=n;i++){
48 fa[i][0]=read();
49 ans[i]=1e9+1e7;
50 add(fa[i][0],i);
51 }
52 dfs(1);
53 for(int i=2;i<=n;i++)
54 printf("%.10lf\n",calc(i,ans[i]));
55 return 0;
56 }
T3
2021.7.15考试总结[NOIP模拟16]的更多相关文章
- 2021.8.15考试总结[NOIP模拟40]
T1 送花 线段树.枚举右端点,线段树记录左端点对应的值. 每次对当前颜色上上次出现的位置到上次出现的位置区间减,上次出现的位置到当前位置区间加. $code:$ 1 #include<bits ...
- 7.15考试总结(NOIP模拟16)[Star Way To Heaven·God Knows·Lost My Music]
败者死于绝望,胜者死于渴望. 前言 一看这个题就来者不善,对于第一题第一眼以为是一个大模拟,没想到是最小生成树. 对于第二题,先是看到了状压可以搞到的 20pts 然后对着暴力一顿猛调后来发现是题面理 ...
- 2021.10.15考试总结[NOIP模拟77]
\(n=40\)考虑\(meet \;in \;the \;middle\) 某个元素有关的量只有一个时考虑转化为树上问题 对暴力有自信,相信数据有梯度 没了 UPD:写了个略说人话的. T1 最大或 ...
- 2021.9.17考试总结[NOIP模拟55]
有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...
- 2021.7.29考试总结[NOIP模拟27]
T1 牛半仙的妹子图 做法挺多的,可以最小生成树或者最短路,复杂度O(cq),c是颜色数. 我考场上想到了原来做过的一道题影子,就用了并查集,把边权排序后一个个插入,记录权值的前缀和,复杂度mlogm ...
- 2021.9.9考试总结[NOIP模拟50]
T1 第零题 神秘结论:从一个点满体力到另一个点的复活次数与倒过来相同. 于是预处理出每个点向上走第$2^i$个死亡点的位置,具体实现可以倍增或二分. 每次询问先从两个点同时向上倍增,都转到离$LCA ...
- 2021.9.13考试总结[NOIP模拟52]
T1 路径 考虑每一位的贡献,第$i$位每$2^i$个数会变一次,那么答案为$\sum_{i=1}^{log_2n} \frac{n}{2^i}$. $code:$ 1 #include<bit ...
- 2021.8.11考试总结[NOIP模拟36]
T1 Dove玩扑克 考场并查集加树状数组加桶期望$65pts$实际$80pts$,考后多开个数组记哪些数出现过,只扫出现过的数就切了.用$set$维护可以把被删没的数去掉,更快. $code:$ 1 ...
- 2021.9.14考试总结[NOIP模拟53]
T1 ZYB和售货机 容易发现把每个物品都买成$1$是没有影响的. 然后考虑最后一个物品的方案,如果从$f_i$向$i$连边,发现每个点有一个出度多个入度,可以先默认每个物品都能买且最大获利,这样可以 ...
随机推荐
- 用Java写了一个程序,将一个Mysql库中的表,迁移到另外一个server上的Mysql库中
用Navicat做数据迁移,因为数据量比较大,迁移过过程中一个是进展不直观,另外就是cpu占用率高的时候,屏幕跟死机了一样点不动按钮,不好中断. 想了想,干脆自己写一个. 在网上找了一个sqllite ...
- 教你搞懂Jenkins安装部署!
前言:请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i Jenkins介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用 ...
- TypeError: exchange_declare() got an unexpected keyword argument 'type'
在设置消息广播时:以下代码会报错channel.exchange_declare(exchange='direct_logs', type='direct')TypeError: exchange_d ...
- Apollo 配置中心详细教程
一.简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理 ...
- 【优化技术专题】「温故而知新」基于Quartz系列的任务调度框架的动态化任务实现分析
不提XXLJOB或者其他的调度框架,就看我接触的第一个任务调度框架Quartz(温故而知新) Quartz的动态暂停 恢复 修改和删除任务 实现动态添加定时任务,先来看一下我们初步要实现的目标效果图, ...
- Android学习记录(二)——第一次hello world及遇到的gradle安装问题
开始一个简单的hello world项目,简单了解Android studio的使用方法 第一步,打开Android studio,点击Create New Project 第二步,选择需要的模板 T ...
- leetcode 盛水最多的容器 解析
采用双指针法: 主要思想:定义头尾两个指针,分别向中间遍历,当相遇时结束循环.存储每一次遍历容器盛水的最大容量,并不断更新. 盛水的最大容量为 左右指针高度的最小值 乘以 左右指针的距离即宽度. 则可 ...
- seo执行步骤
第一个金字塔策略这个很适用于大型网站,我想做过大型网站,特别是关键词比较多比较杂乱的站长来说,这个图太熟悉不过了,就算是没有见过,但实际操作中早就用到了这些手法.如果能把这个图领会透并实际应用,做一个 ...
- javascript LinkedList js 双向循环链表 Circular Linked List
javascript LinkedList: function Node(elem, prev, next) { this.elem = elem; this.prev = prev ? prev : ...
- P3211-[HNOI2011]XOR和路径【高斯消元】
正题 题目链接:https://www.luogu.com.cn/problem/P3211 题目大意 一个\(n\)个点\(m\)条边的无向图,从\(1\)到\(n\)随机游走.求期望路径异或和. ...