2019 BUPT Winter Training #5 div2 题解

比赛链接

A - Friends (HDU 5305)

题意

给一张图有n个点,m条无向边。让你给每条边染成红色或黑色。使得每一个点相连的所有边中,红色边和黑色边的条数相等。

问有多少种染色方式。

解法

因为最多只有8个点,28条边。直接暴力搜索即可。只要代码别写(的像我一样)挫就行。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

#define print(x) cout << x << endl
#define input(x) cin >> x

class Solution {
public:
    Solution(int n_, int …
more ...

白话一致性协议 - Paxos、Raft和PacificA[2]

PacificA是一个框架

虽然在题目中我们把Paxos、Raft和PacificA并列,但是Paxos和Raft在论文中称自己为一种“算法”(algorithm);而PacificA对自己的定位是一种通用的,强一致的数据同步框架

在论文中,作者提到现有的可证明的数据同步协议往往过分简化了性能问题,导致看起来很美的理论设计无法转变有实际的系统(注:本篇论文应该早于Raft的论文)。所以作者的目标是将算法理论与实际相结合,进行相应的系统设计。

PacificA的实现

与Paxos和Raft不同的是,PacificA采用的算法非常简单。所以在这里我不进行太多铺垫,直接进入正题。

主从同步

PacificA使用了主从同步模型,用户的读写请求都会发往主节点,以保证强一致性。

主节点会对发来的写请求进行编号,使得所有写请求编号唯一且单调递增。这个编号也会同步到从节点。

无论是主节点还是从节点,所有的写请求都写入一个只追加的日志。主从节点都需要维护committed指针,代表在这个指针之前的数据都已经被所有节点所认可,处理“已确认”状态。从节点需要额外维护一个prepared指针,代表在这个指针之前所有的数据都处于“待确认”状态,而在prepared指针之后的数据,都是“待同步”状态。

主从之间的数据同步使用两步提交模型 …

more ...

2019 BUPT Winter Training #3 div2 题解

写在前面

做为一个年近半百的中年人,还能厚着脸皮蹭学弟学妹们的训练赛。真是开心啊。

A - Constellation (CF 618C)

题意

在二维平面上给定一堆整数点,求任意一个三角形,使得三角形内以及其边上,不包含其它的点。

解法

我们先从一条边想起。选定任意一个点,从这个点引出的最短边上,一定不包含其它的点。(非常直观)

与这个思路类似,选定这条边之后,从这个边引出的面积最小的三角形,一定也不包含除三角形三点以外的其它点。

求三角形面积可以使用向量的叉积。

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;

#define print(x) cout << x << endl …
more ...

C++类型擦除与`std::function`性能探索

什么是类型擦除

对于Python这种动态类型语言来说,是不存在“类型擦除”这个概念的。Python对象的行为并不由接口定义,而是由“当前方法和属性的集合”决定。

所以,以下的代码是完全合法的:

class Foo(object):
    def print(self):
        print 'foo'

class Bar(object):
    def print(self):
        print 'bar'

def do_print(obj):
    print obj.print()

do_print(Foo()) // print 'foo'
do_print(Bar()) // print 'bar'

但是对于C++这种静态类型语言来讲,我们就不能使用这种语法:

class Foo {
public:
    void print() { cout …
more ...

在WSL中获取Windows剪贴板中的图片

背景

Win10里面的WSL(Windows Subsystem For Linux)算是一个开发神器了,虽然功能不是100%完善,但是对于轻度开发已经足够了。现在我的日常开发,就是一个全屏CMD跑内部工具,一个全屏WSL跑tmux+vim。

(跑题了)

问题

之前的文章里,我有写到使用github做为图床,并且使用python脚本进行图片上传。但是仍有一点问题,就是之前的脚本只能上传文件,不能直接上传剪贴板里的图片。

解决

发现Windows里面有内置的访问剪贴板工具,但是只在powershell下可用。不过我们可以在WSL里直接调用exe文件(这点非常神奇),然后读出图片文件放入临时文件夹。然后我们再读出这个文件进行上传。

总的流程仍然是上传已有的图片文件,但是我们把它放在临时文件夹并隐藏了起来。看起来就是实现了WSL和Windows剪贴板的互操作。

#!/bin/bash

TMP=/mnt/c/Users/me/AppData/Local/Temp/
TMPWIN=C:\\Users\\me\\AppData\\Local\\Temp\\

ts …
more ...

白话一致性协议 - Paxos、Raft和PacificA[1]

书接上文 - Multi Paxos

在上一篇文章中,我们提到了Basic Paxos和Multi Paxos的异同。在Paxos Made Simple论文中,作者提到了Multi Paxos的一种实现。这个实现允许我们对一个连续的数据流(也可以称为复制日志,replicated log)达成共识,从而实现节点状态的一致性复制。

确定性状态机

我们可以将系统中的每一个节点抽象为一个有着确定性状态机,即给定多个状态一致的状态机,在执行同一个命令之后,其状态仍保持一致。(可以想一想编译原理里面的DFA)

Leader - 系统中唯一的proposer

如果系统中存在有多个proposer,那么就很可能会出现多个提案相互干扰的情况。虽然根据证明,最终这些提案都会收敛到一致,但是性能会非常低下。所以我们可以在系统中通过选举,选出一个leader做为主proposer(distinguishied proposer),所有的提案都由leader提出。

这样一来,在绝大多数情况下都不会出现提案相互干扰的情况。只有在leader切换的瞬间,可能会出现相同编号的不同提案,但是我们的算法可以很好的处理这种情况。

分布式系统中的“TCP”

类似于TCP协议中序列号,Multi Paxos中的每一个命令都有一个递增的编号。即我们前一个执行的命令是100号,那么下一个执行的命令一定是101号 …

more ...

白话一致性协议 - Paxos、Raft和PacificA[0]

一致性协议 - Paxos

在分布式系统当中,我们往往需要保持节点之间的一致性。在绝大多数情况下,我们需要让系统中的节点相互协调通力合作,有可能的让系统正确的工作。但是,由于分布式系统本身的特性,需要我们在不可靠的硬件上尽可能的构建可靠的系统。所以,看似简单的一致性问题成为了分布式系统领域的一个重要的课题。

Paxos算法是Leslie Lamport于1990年提出的一种一致性算法。也是目前公认解决分布式一致性问题最有效的算法之一。

Paxos算法的目标是在一个不可靠的分布式系统内,只通过网络通信,能够快速且正确地在集群内部对某个数据的值达成一致。并且保证不论发生任何异常,都不会破坏系统的一致性。

Paxos算法

另一种(简化了的)形象的问题描述 - 买车位

某小区的一些居民在抢车位,而车位只有一个。居民们达成协议,只要一个报价获得半数以上居民认可,那么提出这个出价的居民则获得了车位的所有权。

居民之间非常友善,如果知道了车位已经有了买家,就不会继续出价购买,并且会帮忙传播这个信息。

居民们都是遵纪守法的好公民,在整个过程中都只会如实的与其它用户分享信息。信息的分享是在网上,通过一对一的私密聊天进行。但是小区的手机信号非常差,我们不能保证通信的质量,一些信息可能会丢失,有的居民可能会掉线。但是居民不会失去记忆,并且通信的内容是完整的,不会被篡改的。

划重点:

  1. 车位有且只有一个,所以一个车位不能同时有两个拥有者
  2. 车位可以暂时没有拥有者,但是需要尽快选出一个 …
more ...

七牛云图床自救指南(附github图床小工具)

背景

之前一直在用七牛云的存储做图床(简称白嫖)。但是免费的午餐必然不会长久,七牛要求所有bucket都要绑定备案过的域名,否则就停掉你的bucket的外链。这事我也不吐槽啥,毕竟是白嫖,也不能要求啥。

但是最智障的是,你外链停了没关系,但是我在后台portal查看文件,上面的图还是显示不了,点下载也没有反应,只显示“ [5402] 获取 bucket 域名失败”。说好不嫖了,你却又不让我走了,都没办法数据迁移的。

因为博客里的图全都存在了七牛的图床上,这么一波搞下来就非常伤。于是我积极展开自救行动。

大侦探毛利小五郎

我:你看我们天天查问题,像不像柯南在查案子?
同事:我觉得我们更像毛利小五郎。

大胆猜测七牛的portal也是使用了外链的URL,如果不绑域名的话,是没有文件的URL的。但是我手里又没有备案后的域名。事情就陷入了僵局。

七牛提供了小工具(qrsctl)让我们管理文件,我觉得这可能是个突破点,万一小工具可以把数据下载下来呢?结果也是不行,这就非常GG了。

此时,我又发现小工具有拷贝数据的功能,可以把跨bucket拷贝数据,但是我的所有的bucket都没有绑域名。也并不能解决问题。

我突然又想到,七牛云其实并没有完全禁止外链 …

more ...

多线程编程初步

前言

非常不喜欢这种“X一峰”式的文章。但是为了伟大的教育事业,还是要写一点的。

线程安全的定义

无论操作系统如何调度线程,无论这些线程的执行顺序如何交织。一个函数(或类)在多个线程同时访问时能表现出正确的行为,而无需调用端代码进行额外的同步或协调操作。

划重点:

  • 无论如何调度
  • 无需额外的同步或协调操作
  • 总能表现出正确的行为

竞态条件(race condition)

竞态条件描述的是一个系统或者进程的输出依赖于不受控制的事件出现顺序或者出现时机。例如两个进程“同时读写”一块内存,其结果一定是不受控制的。

“同时读写”的定义包括:

  • 一读一写
  • 一写多读
  • 多写一读
  • 多写多读
  • 多写

也就是说,只要包含“并发”和“写操作”两个特性,就会出现竞态条件。而“多读”一般来说是安全的。

同时也要注意,这里的读与写是物理意义上的读写,而不是逻辑意义上的。有一些函数看起来只有读操作,但其内部仍然包括了对数据的修改,这里需要注意甄别。

Mutex - 互斥锁 …

more ...

开通了一个新栏目

博客开通了一个新栏目“For Beginners",想把之前写的一些比较适合于初学者的文章发到这里来。

实在是不喜欢博客里都是“XXX入门”、“XXX介绍”这类东西(我并没有针对谁),但是也不想白瞎我在教育事业上付出的心血。

大家勉为其难的看一下,有问题辛苦多做自我批评。

谢谢大家。

more ...