SDU泰山学堂计算机方向算法复习&ACM复习
嘛泰堂没进 所以是 复习了
排序
均以升序排列为例
No.1 冒泡排序
简单直接的一个排序算法
把相邻元素进行比较,最大的往后换,每轮的最后一个位置的数一定是该轮中最大的
时间复杂度
代码实现
#include <bits/stdc++.h>
#define N 500005
#define re register int
#define Endl cout << '\n'
using namespace std;
void Fastio_setup() { ios :: sync_with_stdio(false) ; cin.tie(NULL), cout.tie(NULL); }
int a[N];
inline void sorting(int tmp[], int tmplen) // 升序排列
{
for (re i = tmplen ; i >= 2 ; -- i) // 排序序列的长度递减,确保次大元素能够移动到对应位置
for (re j = 1 ; j <= i-1 ; ++ j) // 每个元素依次与下一个元素相比
if (tmp[j] > tmp[j+1])
swap(tmp[j], tmp[j+1]);
}
void work()
{
cin >> a[0];
for (re i = 1 ; i <= a[0] ; ++ i)
cin >> a[i];
sorting(a, a[0]);
Endl;
for (re i = 1 ; i <= a[0] ; ++ i)
cout << a[i] << ' ';
Endl;
}
int main()
{
Fastio_setup();
work();
return 0;
}
No.2 选择排序
也是非常的直观,从序列中扫描出最大值,和数组末端互换,再对剩下的元素扫描重复步骤
时间复杂度
代码实现
#include <bits/stdc++.h>
#define N 500005
#define re register int
#define Endl cout << '\n'
using namespace std;
void Fastio_setup() { ios :: sync_with_stdio(false) ; cin.tie(NULL), cout.tie(NULL); }
int a[N];
inline void sorting(int tmp[], int tmplen) // 升序排列
{
int maxx = -0x7fffffff, targ = -0x7fffffff;
for (re i = tmplen ; i >= 2 ; -- i) // 本次扫描长度
{
maxx = -0x7fffffff;
for (re j = 1 ; j <= i ; ++ j)
if (maxx < a[j])
maxx = a[j], targ = j;
swap(a[i], a[targ]);
}
}
void work()
{
cin >> a[0];
for (re i = 1 ; i <= a[0] ; ++ i)
cin >> a[i];
sorting(a, a[0]);
Endl;
for (re i = 1 ; i <= a[0] ; ++ i)
cout << a[i] << ' ';
Endl;
}
int main()
{
Fastio_setup();
work();
return 0;
}
No.3 插入排序
这个算法对于上述两个稳定 的算法有所不同,在不同数据下表现不同,上限是 ,在极特殊条件下(序列原本就有序)直接做到了
算法思想:将数组最左端的元素视为有序序列,每次向右拓展一个,向右拓展的该元素与有序序列的元素从右往左依次比较,将其插入到合适的位置,有序序列因此扩增,循环往复直至全体序列有序
由于大多数情况下序列都是无序的而且构造在大数据规模下都“差不多”的,所以认为他的时间复杂度仍然为
代码实现
#include <bits/stdc++.h>
#define N 500005
#define re register int
#define Endl cout << '\n'
using namespace std;
void Fastio_setup() { ios :: sync_with_stdio(false) ; cin.tie(NULL), cout.tie(NULL); }
int a[N];
inline void sorting(int tmp[], int tmplen) // 升序排列
{
int val = 1;
for (re i = 2 ; i <= tmplen ; ++ i) // 有序序列长度+1
{
val = tmp[i];// 待插入元素
for (re j = i-1 ; j >= 1 ; -- j) // 有序序列从后向前扫描
{
if (val >= tmp[j])
{ tmp[j+1] = val; break; }
else
tmp[j+1] = tmp[j];
}
}
}
void work()
{
cin >> a[0];
for (re i = 1 ; i <= a[0] ; ++ i)
cin >> a[i];
sorting(a, a[0]);
Endl;
for (re i = 1 ; i <= a[0] ; ++ i)
cout << a[i] << ' ';
Endl;
}
int main()
{
Fastio_setup();
work();
return 0;
}
博弈
图论
这玩意以前好像就没弄明白原理
重新看一遍博客感觉还是有点怪(为啥遍历一遍就能全min了)
不过差不多知道原理了
先说 的
从离源点最近的点 ,然后遍历他的每个出边更新 的 dis
值
在整个dis
里找到最小值作为新的
找 不会超过 次所以索性直接循环 次
这就是朴素的 。
堆优化是把找 dis
的过程用优先队列优化掉
这样的复杂度就是 了
你可能会问为什么不在更新的时候直接统计 达到 的复杂度,我试了,大概是这样实现:
code
int u = 1, minn = 999999999;
for (int i = 1 ; i <= n ; ++ i) {
for (int j = head[u] ; j ; j = e[j].nxt) {
int v = e[j].v;
if (dis[v] > dis[u] + e[j].w)
dis[v] = dis[u] + e[j].w;
}
minn = 999999999;
for (int j = head[u] ; j ; j = e[j].nxt) {
if (dis[v] < minn) {
u = v;
minn = dis[v];
}
}
}
因为在上一轮可能有两个比较小的 ,这次再扫的新的点里可能不包含上一轮的次小 ,导致漏掉点。
堆优化:
code
void Dijkstra() {
memset(dis, 0x7f, sizeof(dis));
// cerr << dis[0] << '\n';
dis[st] = 0; q.push((node){0, st});
while (q.empty() == false) {
node tmp = q.top(); q.pop();
if (vis[tmp.pos] == false) { // 以此点向外拓展
vis[tmp.pos] = true;
for (int i = head[tmp.pos] ; i ; i = e[i].nxt) {
if (dis[e[i].v] > dis[tmp.pos] + e[i].w) {
dis[e[i].v] = dis[tmp.pos] + e[i].w;
q.push((node){dis[e[i].v], e[i].v});
}
}
}
}
}
数据结构
No.1 线段树
代码实现
#include <iostream>
#include <cstdio>
#include <map>
#include <cstring>
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define MIN(a, b) (((a) > (b)) ? (a) : (b))
#define Endl cout << '\n'
#define _ ' '
#define N 100005
using namespace std;
void Fastio_setup() { ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
/*
浅复习一下线段树
写对了,但是估计需要加lazytag
我想想咋写的
*/
int n, Q;
long long a[N];
struct Segment_Tree
{
struct node { long long sum, lz; };
struct node tr[N << 2];
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define mid ((l + r) >> 1)
inline void Pushup(int rt, int l, int r) { tr[rt].sum = tr[lson].sum + tr[rson].sum; }// + tr[lson].lz*(mid-l+1) + tr[rson].lz*(r-mid); }
/*inline void Pushdown(int rt)
{
tr[lson].lz = tr[rt].lz;
tr[rson].lz = tr[rt].lz;
}*/// 算了一会再写lazytag的
inline void Pushdown(int rt, int l, int r)
{
// tr[lson].sum += tr[lson].lz * (mid-l+1);
// tr[lson].lz = tr[rt].lz;
// tr[rson].sum += tr[rson].lz * (r-mid);
// tr[rson].lz = tr[rt].lz;
// Pushup(rt, l, r); tr[rt].lz = 0;// 一会会Pushup的
tr[lson].lz += tr[rt].lz;
tr[rson].lz += tr[rt].lz;
tr[lson].sum += tr[rt].lz * (mid-l+1);
tr[rson].sum += tr[rt].lz * (r-mid);// lz不会上传,upd时候没有给儿子更改lz因此现在加是真的
tr[rt].lz = 0;
}
void Build(int rt, int l, int r)
{
if (l == r)
{ tr[rt].sum = a[l]; return ; }
Build(lson, l, mid);
Build(rson, mid+1, r);
Pushup(rt, l, r);
}
void Update(int rt, int l, int r, int L, int R, long long val)
{
if (L <= l and r <= R)
{ tr[rt].lz += val; tr[rt].sum += val * (r-l+1); return ; } // 先不乘
if (tr[rt].lz != 0)
Pushdown(rt, l, r);
if (L <= mid)
Update(lson, l, mid, L, R, val);
if (R > mid)
Update(rson, mid+1, r, L, R, val);
Pushup(rt, l, r);
}
long long Query(int rt, int l, int r, int L, int R)
{
if (L <= l and r <= R)
{ return tr[rt].sum; }
if (tr[rt].lz != 0)
Pushdown(rt, l, r);
// Pushup(rt, l, r); // 呃
if (R <= mid)
return Query(lson, l, mid, L, R);
else if (L > mid)
return Query(rson, mid+1, r, L, R);
else
return (Query(lson, l, mid, L, R) + Query(rson, mid+1, r, L, R));
}
#undef lson
#undef rson
#undef mid
};
struct Segment_Tree Segment;
void work()
{
cin >> n >> Q;
for (int i = 1 ; i <= n ; ++ i)
cin >> a[i];
Segment.Build(1, 1, n);
int opt, x, y; long long k;
while (Q --)
{
cin >> opt;
if (opt == 1)
{
cin >> x >> y >> k;
Segment.Update(1, 1, n, x, y, k);
}
else
{
cin >> x >> y;
cout << Segment.Query(1, 1, n, x, y) << '\n';
}
}
}
int main() {
// freopen("T.in", "r", stdin);
// freopen("T.out", "w", stdout);
Fastio_setup();
work();
return 0;
}
笛卡尔树
第一场网络预选赛考到了导致我强行学习
原来是个二叉树+堆啊
做题时候想到了所以终于印象深刻
对于任一个节点 ,满足性质:
-
id[lson] <= id[x] <= id[rson]
-
val[x] > val[lson], val[rson]
由于pos是连续的所以中序遍历是原代号(任意x的子树中)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!