Contents

ARST打卡第236周[236/521]

Algorithm

lc715_Range模块

思路: 暴力算法就是维护一个pair对,或者直接用kv的map,然后就直接按照key排序了。

这样每次直接根据k-range的左值进行范围查找和计算。

两个 k-range 只有包含,交叠和错开三种状态,所以只要进行处理就行。

这里实现的关键是 lower_bound 对 key 操作是否能实现。 然后时间复杂度是 O(nlog(n)) , n 为最多查询次数。 空间复制度是 O(2n)。

不太熟这个操作,写代码时间超时了,学习一下题解吧。

发现思路和题解完全一样,但是自己的实现速度和坚定度不够,还得多多练习。 并且这里时间复杂度分析把后面的操作算成时间常数,只算了 log(a+r) , 所以时间复杂度也得更细致一点。

给题解加点注释。 发现思路很简单,但是很考验实现速度和精细度。以后还得多练。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class RangeModule {
public:
    RangeModule() {}
    
    void addRange(int left, int right) {
        // 先找大于 left 的,然后 prev 获取前一个,就能保证 pre_l <= left.
        auto it = intervals.upper_bound(left);
        if (it != intervals.begin()) {
            auto start = prev(it);
            // 在前面,pass
            if (start->second >= right) {
                return;
            }
            // 交叠处理
            if (start->second >= left) {
                left = start->first;
                intervals.erase(start);
            }
        }
        while (it != intervals.end() && it->first <= right) {
            right = max(right, it->second);
            it = intervals.erase(it);
        }
        // it 在最开始找不到时也能顺利到这里。妙。
        intervals[left] = right;
    }
    
    bool queryRange(int left, int right) {
        auto it = intervals.upper_bound(left);
        if (it == intervals.begin()) {
            return false;
        }
        it = prev(it);
        return right <= it->second;
    }
    
    void removeRange(int left, int right) {
        auto it = intervals.upper_bound(left);
        if (it != intervals.begin()) {
            auto start = prev(it);
            if (start->second >= right) {
                // 从中间切成两段
                int ri = start->second;
                if (start->first == left) {
                    intervals.erase(start);
                }
                else {
                    start->second = left;
                }
                if (right != ri) {
                    intervals[right] = ri;
                }
                return;
            }
            else if (start->second > left) {
                // 交叠
                if (start->first == left) {
                    intervals.erase(start);
                }
                else {
                    start->second = left;
                }
            }
        }
        while (it != intervals.end() && it->first < right) {
            // right太大,包括删除的范围就多
            if (it->second <= right) {
                it = intervals.erase(it);
            }
            else {
                intervals[right] = it->second;
                intervals.erase(it);
                break;
            }
        }
    }

private:
    map<int, int> intervals;
};

Review

【TED演讲】你不知道未来的自己想要什么

未来不可知,你不知道未来的自己的想法。 我们可以通过下面三种方式去培育自己让自己成为更好的人:

保持好奇心,保持谦卑,保持勇敢。

Tips

linux学习——软链接、硬链接与复制的区别

Share

vps预览hugo

简单快速预览

因为没有发布,所以一般只能在本地预览,如果是本地操作系统,可以直接查看,但是vps的话,无法直接输出网址查看页面状况。可以通过借助 python 的 http.server 进行简单预览

1
python3 -m http.server 8001

高级预览

如果想要完整预览,还是得用 Nginx 搞个服务,让服务器的 ip 和 port 端口开启对外服务

1
2
# 安装nginx(顺便安装网络排查工具 net-tools)。centos 用 yum install nginx
apt install nginx net-tools
1
2
# vim 配置文件,加上如下配置在 http 的作用域里面
vim /etc/nginx/nginx.conf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# http.server 80 
server {
    # ipv4,ipv6 的 80 端口监听
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  us.wolfdan.cn;     # 你的域名
    root         /root/wolfdan.cn/public; # 公开的静态文件路径__不建议放root下,见后文问题排查

    include /etc/nginx/default.d/*.conf;

    location / {
    }

    error_page 404 /404.html;
    location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    }
}
1
2
3
# 启动 nginx 报错
[root@us-arm public]# nginx
nginx: [emerg] a duplicate default server for [::]:80 in /etc/nginx/nginx.conf:66

需要注释掉默认的 nginx 静态欢迎网页

1
2
- include /etc/nginx/sites-enabled/*;
+ # include /etc/nginx/sites-enabled/*;
1
2
3
4
# 启动 nginx
nginx 
# 重启 nginx
nginx -s reload

访问 http://us.wolfdan.cn:80/ 得到的是 403 … 查看日志发现目录权限不够:

1
2
[root@us-arm public]# tail /var/log/nginx/error.log  -n 1
2023/11/09 09:57:57 [error] 866439#866439: *2 "/root/wolfdan.cn/public/index.html" is forbidden (13: Permission denied), client: 141.98.11.60, server: us.wolfdan.cn, request: "GET / HTTP/1.1", host: "141.148.143.17"

观察发现跑 nginx 是一个 www-data 的虚拟用户

1
2
3
4
5
6
7
[root@us-arm wolfdan.cn]# ps aux | grep nginx
root      797588  0.0  0.0  50572  6344 ?        Ss   09:41   0:00 nginx: master process nginx
www-data  866439  0.0  0.0  51192  5980 ?        S    09:52   0:00 nginx: worker process
www-data  866440  0.0  0.0  51192  5980 ?        S    09:52   0:00 nginx: worker process
www-data  866441  0.0  0.0  51192  5980 ?        S    09:52   0:00 nginx: worker process
www-data  866442  0.0  0.0  51192  5980 ?        S    09:52   0:00 nginx: worker process
root     1107736  0.0  0.0   7700   680 pts/0    S+   10:28   0:00 grep --color=auto nginx

那就设置 public 目录权限为 www-data .

1
[root@us-arm wolfdan.cn]# chown -R www-data:www-data public

改完还是403,很奇怪…

通过设置 nginx.conf 的 user www-data; 改成 user root; 再 pkill -9 nginx && nginx 重启之后是能够访问页面的。

但是 www-data 为啥不行?

感觉是因为 /root 目录下有特殊的保护机制(原因见下文),导致不行,因为通过尝试复制到其他目录,就成功了…

1
2
[root@us-arm wolfdan.cn]# cp -R public/ /var/www/
[root@us-arm wolfdan.cn]# nginx -s reload

然后想到之前 windows 也无法访问 wsl 的 root 目录,于是明白了是因为 root 目录默认不让其他用户访问.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[root@us-arm /]# ll
total 72
drwxr-xr-x  19 root root  4096 Oct 14 18:17 ./
drwxr-xr-x  19 root root  4096 Oct 14 18:17 ../
lrwxrwxrwx   1 root root     7 Jul 20 05:44 bin -> usr/bin/
drwx------   2 root root 16384 Jul 20 05:56 lost+found/
# ...
dr-xr-xr-x 246 root root     0 Oct 14 18:17 proc/
# 看这里是无法让其他用户访问的。
drwx------  11 root root  4096 Nov  9 10:57 root/
# ...
drwxr-xr-x  14 root root  4096 Nov  9 09:19 var/

预览生成的网页

查看发现并没有看到对应的 hello hugo 的文章,是因为默认是 draft ,需要如下方式生成一下。

1
2
3
4
5
6
# *--buildDrafts: 生成被标记为 「草稿」 的文档
# *-w: 监控更改,如果发生更改直接显示到博客上 (保存即可预览效果)
hugo server --buildDrafts -w

# 生成最终文章
hugo 

编辑一个脚本直接发到 nginx 目录下

1
2
3
4
5
6
7
8
9
[root@us-arm wolfdan.cn]# vim deploy.sh
[root@us-arm wolfdan.cn]# cat deploy.sh
# 部署到nginx
# rm -rf /var/www/public
cp -R public/ /var/www/
chown -R www-data:www-data /var/www/public
[root@us-arm wolfdan.cn]# sh -x deploy.sh
+ cp -R public/ /var/www/
+ chown -R www-data:www-data /var/www/public

发现还是没有成功看到草稿文章,然后手动去修改了 draft 标签,再次进行上面的生成步骤

1
2
3
4
5
6
7
[root@us-arm wolfdan.cn]# cp content/post/hello-hugo.md content/post/hello-hugo-public.md
[root@us-arm wolfdan.cn]# vim content/post/hello-hugo-public.md
# 修改为 draft = false
[root@us-arm wolfdan.cn]# hugo
[root@us-arm wolfdan.cn]# bash -x deploy.sh
+ cp -R public/ /var/www/
+ chown -R www-data:www-data /var/www/public