zoukankan      html  css  js  c++  java
  • 常见算法和数据结构存在的坑(updating)

    数组:

    c++数组下标都+5会稳。
    (5000*5000)的别开(6000*6000)

    二分:

    实数二分可能因为神马精度问题出现了不满足二分序的情况,要小心。

    注意二分完后,不能直接用当前数组里存的值,要pd(ans),值才是正确的。

    边集数组:

    无向图边的范围要开2倍

    多组数据要清空的有tot,final

    当用到反向边的时候,tot初值为1(一定要记得赋值)

    分解质因数:

    for(int i = 1; i <= p0 && (ll) p[i] * p[i] <= n; i ++) if(n % p[i] == 0) {
    

    注意只预筛(sqrt n)以内的质数时,一定要加上i<=p0,因为n是((p[p0]^2,maxn])内的一个大质数时,就会循环到外面去。
    或者多筛一点,比如说(sqrt n + 100)

    随机:

    rand()的取值是([0,RAND\_MAX])
    windows下,(RAND\_MAX = 2^{16}-1)
    Linux下,(RAND\_MAX = 2^{32}-1)

    random_shuffle有点假,当随机性要求高时建议自己随机交换:

    i = 1 -> n
        swap(a[i], a[rand(i, n)])
    //理论上面的这个比下面的优
    i = 1 -> n
        swap(a[i],a[rand(1, n)])
    //std ::random_shuffle是下面这么写的
    i = 1 -> n
        swap(a[i], a[rand(1, i)])
    

    set:

    不要把multiset写成set了。

    且multiset重载<时需要注意不能只重载了值,其余的附带信息最好也加进后续的关键字,不然在erase就会出锅。

    线段树:

    普通线段树:

    如果下标有负数的话一定要用位运算,不然会GG。

    int m = x + y >> 1;
    

    x,y为int里面的整数,但是(x+y)可能爆int。

    不下传标记线段树:

    矩形覆盖问题只能用不下传标记线段树,千万不要卡死在普通线段树上。
    而且不下传标记线段树局限性很大。

    treap:

    随机手写会快,但不要伪了
    要维护fa时,可以在upd时更新,但是在split和merge开头,需要:

    fa[son[x][0]]=fa[son[x][1]]=0
    

    因为中间过程中可能把一个点的儿子设空,而这个儿子又没有新的父亲,就更新不到了

    网络流:

    网络流多组数据清空的有:
    边集数组,co,d,cur,其实就是全部要清空

    上下界网络流:

    最小流的时候,(S)(T)互换,一般清空(1 sim T)的点,就会清不到(S),就错了。

    所以要(1 sim max(S,T))

    第一步的真实流量不是(SS->TT)的流量,而是(T->S)那条(infty)的边的流量。

    字符串:

    exkmp:

    自我匹配时要预处理next[2]。

    manacher:

    若r包括当前这个点,实际最长回文子串长度等于max(r)-1。

    SA:

    如果有多组数据,则height那里要加一句话,因为字符串的后面可能出事。

    原代码:

    
    int j, k = 0;
        for(int i = 1; i <= n; Height[rank[i ++]] = k) 
            for( k = k ? k - 1 : k, j = SA[rank[i] - 1]; a[i + k] == a[j + k]; ++ k);
    

    现代码:

    int j, k = 0;
        for(int i = 1; i <= n; Height[rank[i ++]] = k) 
            for( k = k ? k - 1 : k, j = SA[rank[i] - 1]; a[i + k] == a[j + k] && (i + k <= n) && (j + k <= n); ++ k);
    

    更新:
    另一种写法,把s[0]和s[n+1]赋inf即可

    ps.:
    SA还有一个坑,在多组数据时会挂:

    int cmp(int *f, int x, int y, int z) { return f[x] == f[y] && f[x + z] == f[y + z];}
    

    观察这一句话,是存在越界风险的:
    当f[x]=f[y]时会执行后面那句话,那么x+w-1、y+w-1都必须<=n,f[x]才可能=f[y]
    假设x+w-1=n,则f[x]==f[y]依然可能,此时f[x+w]就越界。
    一般来说数组都会开大几位,如果默认是0,则没有问题。
    但是多组数据中不是默认为0的,所以要清空后一位。

    AC自动机:

    标记一定要沿fail链传一下。

    SAM:

    广义要宽搜。
    如果深搜建广义,就会有空点,然后一些性质就炸了。

    高斯消元:

    实数的话要预先把系数归一,详情见板。

    splay:

    在splay里比如说找中序遍历第k个点,找完之后一定要把那个点splay一下,不然可能会跑得极慢。

    lct:

    access(x)以后x不是所在splay的根,为了方便可以改一下access的写法,最后加一个splay。

    cut时,pf[x]也要清空。

    link时,最好把x,y都makeroot了,不然在奇妙的子树维护下可能会出锅。

    FFT:

    FFT做的其实是一个循环卷积。
    如果(A*B=C),其实式子是这样的:
    (sum_{i=0}^n sum_{j=0}^nC_{(i+j)~mod~n}+=A_i*B_j)

    这就是为什么要取>=n的最小的2的幂*2的原因。

    所以如果有多次FFT,每次做完一定要清空下标大于等于n的。

    注意这里说的n是次数界,如果下标最大是n,次数界是n+1

    还有如果是一个小mo数,就是一定要算好每次数的范围,如果太大就不能NTT(除非取多个模数),就要用long double去FFT。

    拉格朗日插值自然数幂和:

    其实拉格朗日插值不背这个锅。

    只是一个n次的多项式一定要n+1点才能确定位置。

    而幂次是n的自然数幂和是一个n+1次的多项式,所以要插n+2个值。

    一般插0-n+1。

    凸包:

    起点设为最上最左的可以使建完的凸包的向量的几角(atan2(y,x))递增。

  • 相关阅读:
    [原创]全新IFPGA-Cable----支持Xilinx/Altera/Lattice JTAG和UART
    [原创]Modelsim后仿真
    [原创]iFPGA-USB2.0 FT2232H USB & UART开发板使用说明
    [原创]X-HDL 4.2安装与使用
    [原创][Synth 8-2543] port connections cannot be mixed ordered and named ["*_Top.v":1151]
    [原创]..OBJgpio.axf: error: L6002U: Could not open file ..objgpio.o: No such file
    [原创]Zynq SDIO WIFI SotfAP调试
    [原创]时序图新画法
    [原创]基于Zynq SDIO WIFI 2.4G/5G SotfAP STA
    [原创]Zynq AXI-CDMA的使用
  • 原文地址:https://www.cnblogs.com/coldchair/p/11111417.html
Copyright © 2011-2022 走看看