当前位置: 首页 > news >正文

高一讲课

又叫后进先出表

给出一个栈常用功能的实现

struct sta{int tp,a[(int)1e7];void push(int x){a[++t]=x;}int top(int x){if(t==0)return -1;return a[t];}int size(){return t;}void pop(){if(t==0)return ;else t--;}
}s;

push(x) 向栈内压入一个元素

top() 查询栈顶

pop() 弹出栈顶

size() 栈中元素个数

单调栈

问题引入

P5788

维护一个栈,使得栈中元素单调

考虑如何维护一个栈内元素递增的栈:

1.若栈为空或栈顶大于当前元素,直接压入当前元素

2.弹出栈顶

我们发现使某个位置弹出栈的元素编号就是这个位置的答案

于是得到以下代码

#include<bits/stdc++.h>
using namespace std;
int a[1000000*4];
int f[1000000*4];
stack<int> s;
void expush(int x){while(!s.empty()&&a[x]>a[s.top()]){f[s.top()]=x;s.pop();}s.push(x);
}
int main(){cin.tie(0);ios::sync_with_stdio(false);int n;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];for(int i=1;i<=n;i++){expush(i);}for(int i=1;i<=n;i++)cout<<f[i]<<" ";
}

例题

P10334

考虑无解,由于一个时刻只能做一杯饮料,所以当饮料数大于当前时刻,直接输出无解.

倒序计算出相邻两个顾客顾客之间的间隔,尽量在最晚的时间做好.

P10798

取反操作对绝对值限制无意义,只可能通过改变端点值改变威胁区间个数

P9461

P10174

P7167

""水会流入半径大于这个圆盘的圆盘中"",容易想到单调栈.

把圆盘向其后第一个半径大于他的连边,构建出一棵树(根节点为水池),倍增维护.

队列

先进先出表

队列常用功能

struct ccc{int a[1000000],t=0,h=1;void push(int x){a[++t]=x;}void pop(){h++;}int front(){return a[h];}int size(){return t-h+1;}bool empty(){return (t-h+1)==0;}
}q;

单调队列

问题引入

......

考虑维护一个由队首到队尾单调的队列,队首即为该区间的答案

以区间最大值为例:

  1. 如果队首元素不在当前区间内,则弹出队首
  2. 若队尾小于当前元素,弹出队尾
  3. 当前元素入队

代码如下

 h=1,t=0;for(int i=1;i<=n;i++){while(h<=t&&q2[h]+m<=i) h++;while(h<=t&&a[i]>a[q2[t]]) t--;q2[++t]=i;if(i>=m) printf("%d ",a[q2[h]]);}
}

例题

P2827

经典老题

暴力: 堆模拟,注意其余蚯蚓的长度会增加.

正解: 排序,发现 切之前,前半段,后半段分别单调,开三个队列维护

P6033

同上

P4944

deque的应用,应该都做了.

小根堆

priority_queue<int,vector<int>,greater<int> >q;

大根堆

priority_queue<int>q;

DAG

谁把这玩意放这儿的?

性质

  1. 能拓扑排序的图一定是有向无环图,有向无环图一定能拓扑排序.
  2. 从一个点出发,一定不会回到这个点

拓扑排序

拓扑排序要解决的问题是如何给一个有向无环图的所有节点排序。

因此我们可以说 在一个 DAG(有向无环图) 中,我们将图中的顶点以线性方式进行排序,使得对于任何的顶点 \(u\)\(v\) 的有向边 \((u,v)\) , 都可以有 \(u\)\(v\) 的前面。

还有给定一个 DAG,如果从 \(i\)\(j\) 有边,则认为 \(j\) 依赖于 \(i\) 。如果 \(i\)\(j\) 有路径( \(i\) 可达 \(j\) ),则称 \(j\) 间接依赖于 \(i\)

拓扑排序的目标是将所有节点排序,使得排在前面的节点不能依赖于排在后面的节点。

构造拓扑序列

  1. 从图中选择一个入度为零的点。
  2. 输出该顶点,从图中删除此顶点及其所有的出边。

重复上面两步,直到所有顶点都输出,拓扑排序完成,或者图中不存在入度为零的点,此时说明图是有环图,拓扑排序无法完成。

Kahn 算法

算法流程

初始状态下,集合 \(S\) 装着所有入度为 \(0\) 的点, \(L\) 是一个空列表。

每次从 \(S\) 中取出一个点 \(u\) (可以随便取)放入 \(L\) , 然后将 \(u\) 的所有边 \(( u , v_1) , (u, v_2), (u, v_3)\) 删除。对于边 \((u, v)\) ,若将该边删除后点 \(v\) 的入度变为 \(0\) ,则将 \(v\) 放入 \(S\) 中。

不断重复以上过程,直到集合 \(S\) 为空。检查图中是否存在任何边,如果有,那么这个图一定有环路,否则返回 \(L\)\(L\) 中顶点的顺序就是构造拓扑序列的结果。

int n, m;
vector<int> G[MAXN];
int in[MAXN];  // 存储每个结点的入度bool toposort() {vector<int> L;queue<int> S;for (int i = 1; i <= n; i++)if (in[i] == 0) S.push(i);while (!S.empty()) {int u = S.front();S.pop();L.push_back(u);for (auto v : G[u]) {if (--in[v] == 0) {S.push(v);}}}if (L.size() == n) {for (auto i : L) cout << i << ' ';return true;}return false;
}

关于例题,你们会在晴空幻梦的tarjan例题里见到的,这里先放两道简单的.

最小生成树

定义

在图的边集中选择 \(n - 1\) 条,将所有顶点连通。

Kruskal

为了造出一棵最小生成树,我们从最小边权的边开始,按边权从小到大依次加入生成树,如果某次加边产生了环,就扔掉这条边,直到加入了 \(n-1\) 条边,即形成了一棵树.

查询两点是否连通和连接两点可以使用并查集维护。

#include<bits/stdc++.h>
using namespace std;
int fa[10000000];
struct edge{int u,v,w;
}e[10000000];
bool xx(edge a,edge b){return a.w<b.w;
}
int get(int x){if(fa[x]==x)return x;return fa[x]=get(fa[x]);
}
int main(){int n,m;cin>>n>>m;for(int i=1;i<=m;i++)cin>>e[i].u>>e[i].v>>e[i].w;for(int i=1;i<=n;i++)fa[i]=i;sort(e+1,e+m+1,xx);int cnt=0,ans=0;for(int i=1;i<=m;i++){int fx=get(e[i].u),fy=get(e[i].v);if(fx==fy)continue;fa[fx]=fy;cnt++;ans+=e[i].w;if(cnt==n-1){cout<<ans;return 0;}}puts("orz");return 0;
}

prim

基本思想是从一个结点开始,不断加点.

具体来说,每次要选择距离最小的一个结点,以及用新的边更新其他结点的距离。

其实跟 Dijkstra 算法一样,每次找到距离最小的一个点,可以暴力找也可以用堆维护。

#include<bits/stdc++.h>
#define mr make_pair
using namespace std;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >  q;
struct ccc{int to,nxt,w;
}e[(int)1e6];
int head[(int)1e6];
int cnt,tot,ans;
void add(int u,int v,int w){e[++cnt].to=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;
}
int n,m;
int dis[(int)1e6],vis[(int)1e6];
void prim(){for(int i=1;i<=n;i++)dis[i]=1e9,vis[i]=0;dis[1]=0;q.push(mr(0,1));while(!q.empty()){if(tot>=n)return ;int nw=q.top().second,d=q.top().first;q.pop();if(vis[nw])continue;tot++;ans+=d;vis[nw]=1;for(int i=head[nw];i;i=e[i].nxt){int v=e[i].to,w=e[i].w;if(dis[v]>w){dis[v]=w;q.push(mr(w,v));}}}
}

次小生成树

非严格

显而易见地,我们应该用某条未选边替换已选边中的最大边

例如 \(e(u,v,w)\) 我们可以找到生成树上 \(u\)\(v\) 路径上的最大边权,再用当前未选边替换,按此流程遍历所有未选边,答案的最小值即为最终答案.

考虑到生成树是一棵树,所以可以使用树上倍增 LCA 在 \(O(\log n)\) 的时间内处理单次询问.

严格

仍然沿用非严格次小生成树的思想.

考虑特殊情况,即未选边与路径上最大边权值相等的情况,这时我们不能替换最大边,而应替换严格次大边,因此只需多维护一个路径上严格次大边的权值即可.

仍使用树上倍增维护,单次询问 $ O(\log n) $

http://www.gsyq.cn/news/43101.html

相关文章:

  • Ubuntu通过命令行安装REALVNC
  • 下载Google Play 的APK,这样可以不用XAPK
  • 在Ubuntu上配置Nginx实现开机自启功能
  • 阿里云的边缘加速ESA
  • Java映射操作:深入Map.getOrDefault与MapUtils方法
  • 改善深层神经网络:第一周优化算法(二)——Mini-batch 梯度下降汇报总结
  • 有度即时通重拳打击电诈行为,守护企业信息安全
  • 基于pytorch卷积神经网络的汉字识别系统
  • 2025年热门成人自考机构推荐
  • CANopen转Profinet是一种构建于控制局域网设备之上的协议网关
  • 2025年国内成人自考机构口碑推荐榜单:如何选择靠谱的学历提升平台
  • 2025年11月星光喷头厂家推荐排行榜:专业选购与维护指南
  • Spring Cloud Alibaba + Sentinel
  • 德鲁克管理哲学:管理是知行统一的实践创新 - 详解
  • 2025 年 11 月食堂送菜平台推荐排行榜,送菜上门,食堂送菜公司,饭堂送菜平台,专业高效与新鲜直达服务口碑之选
  • 2025 年 11 月电能质量分析仪厂家推荐排行榜,A类/B类电能质量分析仪,动态电能质量监测仪,三相电能质量分析仪,在线检测装置系统公司推荐
  • 2025 年 11 月开窗器厂家推荐排行榜,链条开窗器,机芯开窗器,配件开窗器,优质开窗器公司推荐
  • 2025 年 11 月包装机厂家推荐排行榜,全自动/定量/FFS/25公斤/粉料/颗粒料/肥料/树脂/抽真空/底充式/锂电/零排放/吨袋包装机公司推荐
  • 2025 年 11 月码垛机厂家推荐排行榜,全自动码垛机,高位码垛机,低位码垛机,立柱码垛机,编织袋码垛机,纸箱码垛机,桶码垛机,粉料码垛机,肥料码垛机公司推荐
  • 2025 年 11 月包装称厂家推荐排行榜,全自动/定量/FFS重膜/高速/锂电/零排放/螺旋/吨袋包装称,铜精粉/肥料吨包包装称公司精选
  • gxyz圣经
  • 涡街流量计温度数据的协议桥梁:ModbusRTU转Profinet网关的自动化应用
  • git 添加大文件
  • 第一周--3:使用远程终端登录系统(ubuntu和rocky),并且总结linux系统基础命令
  • 2025年聚硅氧烷漆批发厂家权威推荐榜单:聚硅氮烷漆/防腐油漆厂家/工业防腐漆源头厂家精选
  • 2025 年 11 月民航机票购买,儿童机票购买,国内机票预定平台最新推荐,聚焦资质、服务与口碑的深度解析!
  • 权威认证!EasyCVR平台检测全达标,GB/T28181合规实力再升级
  • mongo内存
  • OIFC 2025.11.7 模拟赛总结
  • Linux - 9 定时任务篇(crontab)