重新回忆一些小 trick

待复习:数论,一些dp,模拟退火,tarjan, 主席树,权值线段树

前缀和差分

F[i][j] = F[i - 1][j] + F[i][j - 1] - F[i - 1][j - 1] + F[i][j];

求一段矩形的和

左上角为 (x, y), 右下角为 (xx, yy)

ans = F[xx][yy] - F[xx][y-1] - F[x-1][yy] + F[x-1][y-1] 

小智慧:

  • 求一组数据中的众数,众数个数大于一半

摩尔投票,两个数不同的情况下一换一,最后剩下的一定是众数。

  • 大部分区间的贪心都是排序右端点。

  • 删边,删点大部分都是离线下来倒序加边,然后树剖就可以了

  • 一些整除问题可以从余数方面考虑。

  • 最长公共子序列,可以通过给 \(a\) 数组升序编号,然后在 \(b\) 中一一对应,这样 \(a\) 的子序列一定是递增的,那 \(b\) 中的递增子序列一定是 \(a\) 的子序列。

字符串

哈希中取出一段哈希值:

\([l,r]=Hash[r]-Hash[l-1]*Pow[r-l+1]\)

模拟退火

退火随机一个二维点:

nowx = limx + ((rand() << 1) - RAND_MAX) * T;
nowy = limy + ((rand() << 1) - RAND_MAX) * T;

退火接受概率的公式:

\(e^{\frac{-del}{T}}?\frac{rand()}{RAND_{MAX}}\)

得看是最大还是最小值了。

退火的模板:

const double lim = ... // 温度最小值,通常为 1e-10 左右
const double d = ... // 变化系数,通常为 0.996 左右
void SA() {
    double T = ... // 初始温度,通常为 2021 左右
    while(T > lim) {
        ... // 获取一个随机的位置
        now = calc(); // 计算当前位置的答案 
        del = now - ans; // 计算 变化量
        if(del < 0) { // 以最小值为例
            ans = now; // 更新答案
            ...  // 更新答案和中间量的状态
        } else if(exp(-del/T) > (double)rand()/RAND_MAX) {
            ...  // 一定概率选择当前当前状态
        } 
        T *= d; // 降温
    }
}

ST 表求 LCA

\([dfn_u+1, dfn_v]\) 中深度最小的点的父亲节点。

注意特判 \(u = v\)

posted @ 2023-11-09 07:49  TLE_Automation  阅读(7)  评论(0编辑  收藏  举报