Contest Summary

本文最后更新于 2 分钟前,文中所描述的信息可能已发生改变。

LeetCode

dataviewjs
// === 配置区 ===
const headers = ["题目", "题目类型"];

// === 数据源 ===
const pages = dv.pages('"posts/contest"')
    .filter(p => p.file.name.includes("lc"))
    .sort(p => p.file.mtime, "desc");

const results = [];

for (const page of pages) {
    const currentFile = page.file;
    const content = await dv.io.load(currentFile.path);
    if (!content) continue;

    // 匹配所有题目标题(## 开头,保留完整标题)
    const problemRegex = /^## \[(\d+\..*?)\]\(.*?\)$/gm;
    const problems = [...content.matchAll(problemRegex)];

    for (let i = 0; i < problems.length; i++) {
        const problemIdTitle = problems[i][1]  // 题号 + 标题
            .replace(/ - 力扣.*$/, "")         // 去掉尾部无关内容
            .trim();

        // 用比赛文件链接替代题目链接
        const problemHeading = `[${problemIdTitle}](${currentFile.path})`;

        // 获取当前题目块内容
        const startIndex = problems[i].index + problems[i][0].length;
        const endIndex = i + 1 < problems.length ? problems[i + 1].index : content.length;
        const problemSection = content.slice(startIndex, endIndex);

        // 匹配“### 题目类型”段落
        const typeMatch = problemSection.match(/^### 题目类型\s*([\s\S]*?)(?=^### |\Z)/m);
        const typeText = typeMatch
            ? typeMatch[1].trim().replace(/\n+/g, " ")
            : "(未标注)";

        results.push([
            problemHeading,
            typeText
        ]);
    }
}

// === 按题号逆序排序 ===
results.sort((a, b) => {
    const numA = parseInt(a[0].match(/\d+/)?.[0] || "0");
    const numB = parseInt(b[0].match(/\d+/)?.[0] || "0");
    return numB - numA;
});

// === 输出结果 ===
dv.table(headers, results);

Codeforces

dataviewjs
// === 配置区 ===
const headers = ["比赛场次", "题目", "题目类型"];

// === 数据源 ===
const pages = dv.pages('"posts/contest"')
    .filter(p => p.file.name.includes("cf"))
    .sort(p => p.file.mtime, "desc");

const results = [];

for (const page of pages) {
    const currentFile = page.file;
    const content = await dv.io.load(currentFile.path);
    if (!content) continue;

    const contestTitle = `[${page.title}](${page.url})`;

    // 匹配所有题目标题(## 开头,保留完整标题)
    const problemRegex = /^## \[(.*?)\]\(.*?\)$/gm;
    const problems = [...content.matchAll(problemRegex)];

    for (let i = 0; i < problems.length; i++) {
        const problemIdTitle = problems[i][1]     // 题号 + 标题
            .replace(/ -\s*Codeforces.*$/i, "")   // 去掉尾部无关内容
            .trim();

        // 用比赛文件链接替代题目链接
        const problemHeading = `[${problemIdTitle}](${currentFile.path})`;

        // 获取当前题目块内容
        const startIndex = problems[i].index + problems[i][0].length;
        const endIndex = i + 1 < problems.length ? problems[i + 1].index : content.length;
        const problemSection = content.slice(startIndex, endIndex);

        // 匹配“### 题目类型”段落
        const typeMatch = problemSection.match(/^### 题目类型\s*([\s\S]*?)(?=^### |\Z)/m);
        const typeText = typeMatch
            ? typeMatch[1].trim().replace(/\n+/g, " ")
            : "(未标注)";

        results.push([
            contestTitle,
            problemHeading,
            typeText
        ]);
    }
}

// === 输出结果 ===
dv.table(headers, results);

错误 & 技巧总结

基础通识

  • 分块 是一种具体实现手段:将数组切分成大小为 n\sqrt{n} 的块,维护每块的统计信息。
  • 根号分治 是一种通用思想:基于问题复杂度分析,以 n\sqrt{n} 为阈值设计不同处理策略。
  • 博弈论任务中,从最终状态回溯获胜者往往很有效。
  • 在动态规划中,用转移来源更新当前状态叫查表法,用当前状态更新其他状态叫刷表法

数学公式

  • 加法

    x+y=2×(x & y)+(xy)x + y = 2 \times (x \text{ \& } y) + (x \oplus y)

  • 阶乘拆分

    (C1+C2++Cn)!C1!C2!Cn!=(C1+C2++CnCn)(C1+C2++Cn1Cn1)(C1+C2C2)(C1C1)\frac{(C_1 + C_2 + \cdots + C_n)!}{C_1! \, C_2! \cdots C_n!} = \binom{C_1 + C_2 + \cdots + C_n}{C_n} \binom{C_1 + C_2 + \cdots + C_{n-1}}{C_{n-1}} \cdots \binom{C_1 + C_2}{C_2} \binom{C_1}{C_1}

交互题

  • 及时刷新缓存,否则会造成Idleness limit exceeded on test 1
python
print(flush=True)

小结

  • 超时:不用使用Counter(),性能很差;
  • 误差:平方根计算使用math.isqrt(),使用int(sqrt())会造成比真实值小11的误差;
  • 超时:用python解题注意数组空间的分配,如10**5及以上量级,可采用哈希表;
  • 预处理:预处理边界要高出给定数据范围,大小按需求设定;
  • 超时:由于python没有纯粹的结构体,可以通过手动压缩减少运行时间,如多维数组压缩成一维数组;
Codeforces Round 1042 (Div. 3)
力扣第 462 场周赛