ORM 是 Object-Relational Mapping(对象关系映射) 的缩写,它是一种编程技术,用于在面向对象编程语言中将数据库表与程序中的对象自动映射,从而避免直接编写繁琐的 SQL 语句。

核心概念

  1. 对象与表的映射

    • 数据库中的一张表 ↔ 程序中的一个类(如 User 类对应 users 表)。
    • 表中的一行数据 ↔ 类的一个实例对象(如 User(name="Alice") 对应表中一行记录)。
    • 表的字段 ↔ 类的属性(如 user.name 对应 users.name 列)。
  2. 操作抽象化

    • 通过操作对象(如 user.save())自动生成并执行底层 SQL(如 INSERT INTO users...),开发者无需手动拼接 SQL。

常见 ORM 框架示例

语言ORM 框架
PythonDjango ORM, SQLAlchemy
JavaHibernate, MyBatis
JavaScriptSequelize, TypeORM
PHPEloquent (Laravel)

优缺点

优点

  • 提高开发效率:减少重复的 SQL 编写。
  • 跨数据库兼容:切换数据库时只需修改配置(如从 MySQL 到 PostgreSQL)。
  • 安全性:内置防 SQL 注入机制(如参数化查询)。

缺点

  • 性能损耗:复杂查询可能不如手写 SQL 高效。
  • 学习成本:需掌握 ORM 的特定语法和约定。

简单示例(Python + SQLAlchemy)

from sqlalchemy import create_engine, Column, String
from sqlalchemy.ext.declarative import declarative_base

# 1. 定义表结构(通过类)
Base = declarative_base()
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

# 2. 创建数据库连接
engine = create_engine('sqlite:///mydb.db')
Base.metadata.create_all(engine)

# 3. 操作数据库(无需写 SQL)
from sqlalchemy.orm import sessionmaker
Session = sessionmaker(bind=engine)
session = Session()

# 插入数据(Create)
new_user = User(name="Alice")
session.add(new_user)
session.commit()

# 查询数据(Read)
users = session.query(User).filter_by(name="Alice").all()

何时使用 ORM?

  • 适合大多数业务逻辑简单的 CRUD 操作。
  • 复杂查询或高性能场景可结合原生 SQL 使用(如 ORM 提供 raw SQL 支持)。

#include <iostream>
#include <set>
using namespace std;
int main()
{
    int n;
    cin >> n;
    set<int> s;
    s.insert(0);
    for (int i = 0; i < n; i ++)
    {
        int a;
        cin >> a;
        if (a < (*s.rbegin()))
        {
            s.erase(s.upper_bound(a));
        }
        s.insert(a);
    }
    cout << s.size() - 1 << endl;
    return 0;
}

启示:

用到了set的特性。除了去重之外,还有一个自动按照从小到大排序,和map一样,因为底层是红黑树,一种平衡二叉搜索树。所以可以有rbegin()取最后一个元素,就是最大元素。这里的逻辑就是让每一个轨道都保持一个单调上升的排序,这样再出去的时候就可以按照从大到小排序的出去(从右往左看)。所以对于每一个数来说如果比最大的还要大就单独开一个序列,如果小于最大的,说明可以找到一个序列使得放进去之后组成的排列时单调上升的,为了可以用最少的轨道,这个放进去的序列最好是最后一个数刚好大于要放进去的数,这里使用到了贪心的思想。为了维护每一个单调上升的序列,只要维护一个序列的最后一个值就好,因为前面的值一定比他大,而且不会拿来做比较,所以可以不看,因此set中实际上是维护了一个所有存在的轨道的序列中的最小值的一个不重复集合。而对于要放入的数来说,可以用upper_bound来找到第一个大于他的数,这个数就是要放入的轨道的最后一个值,将当前数放进去,本质上就是在set中将这个最后的值替换。而因为set中没有索引,但是可以自动排序,根据这一特性,为了完成替换这个操作,我们可以将这个最后一个值在set中删去,最后再将a放去set即可,这就在形式上和另外一种情况保持了统一。最后为了保证形式上的统一,不对第一个数特判,即set为空的情况,可以单独放入一个元素0,因为0一定比所有1到n的数小,所以不会被替换,就不会影响答案。最后的答案要求输出轨道的数量,其实就是set中元素的数量,因为有0的存在,所以实际上的答案是s.size() - 1.

题目:

火车站的列车调度铁轨的结构如下图所示。

188

两端分别是一条入口(Entrance)轨道和一条出口(Exit)轨道,它们之间有N条平行的轨道。每趟列车从入口可以选择任意一条轨道进入,最后从出口离开。在图中有9趟列车,在入口处按照{8,4,2,5,3,9,1,6,7}的顺序排队等待进入。如果要求它们必须按序号递减的顺序从出口离开,则至少需要多少条平行铁轨用于调度?

输入格式:

输入第一行给出一个整数N (2 ≤ N ≤105),下一行给出从1到N的整数序号的一个重排列。数字间以空格分隔。

输出格式:

在一行中输出可以将输入的列车按序号递减的顺序调离所需要的最少的铁轨条数。

输入样例:

9
8 4 2 5 3 9 1 6 7

输出样例:

4

愚人节快乐。

这几天一直过的有点迷茫。

而且莫名的忙和累。

一种委屈感一直藏在心里面,在今天发现大创导师没有帮我提交的时候一下子爆发出来。我有点想哭但是还是找下补救的措施,好在那个管理大创的老师没有为难我,最后还是自己交给她了。

这几天一直在看《心流:最优体验心理学》。

书里面提到的心流感念,是一个我熟悉但是陌生的词汇。

熟悉是因为可能这是一个积极心理学中的专业词汇,所以各种有涉及到心理学,尤其是帮助大家学习的,或者是标题打着如何过好人生的,亦或者是如何快速学会某一种技能的,都或多多少的会提到这个词。由于经常见到,听到,看到,所以我会觉得很熟悉。

但是我又觉得很陌生,因为我回过头发现好像我对于心流之后的概念,以及如何进入心流,还有进入心流状态意味着什么,都是很模糊的,我隐约好像知道点什么,但是好像又回答不具体。这种模糊不仅不会帮助我让我在学习,还有人生路上有任何的启发,反而会让我有某种莫名其妙的自傲,听不进去别人的观点,最后反而没有学习到什么,也没有指导我人生路上的某一段。

在我终于明白了我一直以来的错误观念以及我确实好像需要好好再思考下人生,在这个契机之下我又找到了这本书,这本一直留有印象,但是却从未翻开过的书。

最近一直在看,给我最大的启示就是我可以清晰的根据对于心流体验的定义去判断我是否是在心流状态里面。以及开始寻找内在的奖赏机制去替代外界给予的奖赏机制,事实上这种观点和我以往应试教育时期的思考不谋而合。只不过当时是将这部分应用在了应试,所以仍然是痛苦的。而渐渐的在应试的压力之下我也忘却了这以观点,在看到这本书时,让我又回忆了起来。

只不过我仍然是有疑问的。这种疑问是没有答案的,因为我只是隐约的知道目前的我的生活状态时有问题的,只是暂时没有发现问题出现在了什么地方。我觉得多看看书还是会有启发的。但是在一种很偶然的情况下我发现了一个别人写的博客,也是一个在学生时期写的博客,已经过去很多年了。

看简介这是一个既有读书笔记,又有各种专业知识的疑惑和整理,还有关于算法的整理。我是在找算法题解的时候发现的,因为好奇于这个博客的框架是作者自己写的,还是使用的流行框架,所以点开了首页,看到了介绍。这个时候我想到了我的博客,想起来我好像很久没有更新了。

我又回想起以前还在积极的投入博客创作的时候也是和这位笔者一样,既整理自己的疑惑和知识,也做日常的分享。我在想或许我要是坚持下来了,若干年之后我会不会也会达到和他一样的高度?

在心流:最优体验心理学中的一篇序中写到心流也是有简单复杂之分,心流是将混乱的精神做熵减的过程,而这个过程越复杂,心流的内在也越强大。在这里序言中提到了一个观点就是在选择活动时最好是选择可以训练,有上升空间的。在这个范围之内如果可以选择自己的兴趣就再好不过了,这句话是我自己说的,原序的观点是可以自行选择不同的行为体验心流。

我看到了那个博客中笔者在介绍自己看过的书,有关于计算机相关的,讲述在还不敢逃课的年纪,坐在后排,带上隔音耳塞,偷偷学习数据结构,学习算法。这令我很感动,因为我看到了我高中时在数学课上偷偷看php入门,以及网课时期逃课学习python的时光。我想那个时候的我应该是在朴素的学习编程语言中进入了心流的状态,自己获得了一种内在的满足感,而没有外在的影响(或者说几乎没有,因为选择编程语言,而不是物理学或者人文,本身或就是受到了外界因素的影响,但是在这个过程中自我的满足感对于今天的我来说仍然具有很大的启发性)。

我好像发现其实找回初心对于我来说可能是一个伪命题,就算是找到了,其实最后也会发现仅仅只是想写个程序,做个应用,没有什么很宏大的理想。但是对于我而言编写代码,写点程序,已经是我所熟识的一个技能了(至少是和什么画画,唱歌之类的相比。和真正的大佬比我还是菜,hh)。

最近一直为各种人际往来,各种成绩,政策,这些细小的琐碎的东西所困。或许我还没有树立好远大的目标,远大的理想,没有想好未来要做什么。但至少现在我或许可以重新开始好好探索计算机科学与技术这个大类,捡起我学过的技能,再向外扩展不断学习新的东西,将自己的生活过的充实。

船到桥头自然直,其他的东西暂且不管了。不管是保研也好,还是就业也好,先放到一边吧。至少不是现在。对于我来说,选择计算机类的专业或许是幸运的。希望我可以逐渐地建立起内在的秩序,提高我的专业技能,以后混口饭吃,自得其所就好了。

未来与君共勉!

(ps:其实是4月2日写完的,昨天没写完,今天补上最后几行字,可惜的是由于差了一天,心境大不相同,想来也是遗失了一些感悟。)

错误原因

PowerShell 的执行策略 (Execution Policies) 是保护机制,用于防止运行未经认证的脚本。

解决步骤

以下是解决该问题的几种方法:


方法一:临时修改执行策略(推荐)

  1. 在 PowerShell 中运行以下命令以临时允许脚本运行:

    Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
    
  2. 再次尝试运行你的命令:
    此方法仅对当前 PowerShell 会话有效,关闭终端后执行策略会恢复为默认值。

方法二:永久修改执行策略

这是一个更改系统设置的持久解决方案,仅在你明确需要时使用。

  1. 使用管理员权限运行 PowerShell。
  2. 执行以下命令以修改系统级别的执行策略:

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
    • RemoteSigned 表示允许本地脚本执行,远程下载的脚本需要被签名。
  3. 再次尝试运行你的命令。

注意:永久修改执行策略可能存在一定安全风险,请根据实际需要执行。

url: http://oj.ecustacm.cn/problem.php?id=1455

tag: 搜索

思路:使用bfs或者dfs。如果使用bfs需要将每次的路径也放入队列中,当搜到终点时,就直接将答案输出。使用dfs需要使用一种记忆化的剪枝技巧,每次判断当前的路径长度 + 1和即将到达的那个点的到那个点的最短的长度比较,如果大于就直接跳过,如果小于就更新那个点的值。这种做法含有记忆化搜索的思想。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
char d[31][51];
char r[] = {'D', 'U', 'L', 'R'};
int nx[] = {1, -1, 0, 0};
int ny[] = {0, 0, -1, 1};
int minv = 0x3f3f3f3f;
string res = "";
bool st[31][51];
int mastep[31][51];
void dfs(int len, int x, int y, string ans)
{
    if (x == 30 && y == 50)
    {
        if (len == minv)
        {
            res = min(res, ans);
        }
        if (len < minv)
        {
            minv = len;
            res = ans;
        }
        return;
    }
    for (int i = 0; i < 4; i ++)
    {
        int xx = x + nx[i], yy = y + ny[i];
        if (xx < 1 || xx > 30 || yy < 1 || yy > 50 || st[xx][yy] || d[xx][yy] == '1') continue;
        if (len + 1 > mastep[xx][yy]) continue;
        if (len >= minv) continue;
        st[xx][yy] = true;
        mastep[xx][yy] = len + 1;
        dfs(len + 1, xx, yy, ans + r[i]);
        st[xx][yy] = false;
    }
}
int main()
{
    memset(mastep, 0x3f, sizeof mastep);
    for (int i = 1; i <= 30; i ++)
        for (int j = 1; j <= 50; j ++)
            cin >> d[i][j];
    dfs(0, 1, 1, "");
    cout << res << endl;
    return 0;
}

答案:

#include <iostream>
using namespace std;
int main()
{
    cout << "DDDDRRURRRRRRDRRRRDDDLDDRDDDDDDDDDDDDRDDRRRURRUURRDDDDRDRRRRRRDRRURRDDDRRRRUURUUUUUUULULLUUUURRRRUULLLUUUULLUUULUURRURRURURRRDDRRRRRDDRRDDLLLDDRRDDRDDLDDDLLDDLLLDLDDDLDDRRRRRRRRRDDDDDDRR" << endl;
}