算法笔记

79 阅读3分钟

1.prefix 前缀和数组

p[i] = p[i-1] + a[i];

优点:便于数组查找

2.diff 差分数组

d[i] = a[i] - a[i-1];

优点:便于数组修改

3.二位前缀和

p[i][j] = p[i-1][j] + p[i][j-1] - p[i-1][j-1] + a[i][j];

4.二维差分

1.差分求法

d[i][j] = a[i][j] - a[i-1][j] - a[i][j-1] + a[i-1][j-1]

以上这个求法,是将原式作为所求差分的前缀和。

2.标准求法

d[i][j] += a[i][j];

d[i + 1][j] -= a[i][j];

d[i][j + 1] -= a[i][j];

d[i + 1][j + 1] += a[i][j];

两种求法一样,可以互相推导

eg:d[i + 1][j] -= a[i][j]; = d[i][j] -= a[i-1][j]

2.位运算双指针排序二分

1.位运算

与:&

或:|

非:!

异或:^ (任何数,与0进行异或都等于0)eg:【a + b = 2(a & b)+ (a ^ b)】

移位:<< (左移),>>(右移)

取反:~

bitset<n>(x)   //将x转换为n进制
x <<= 1        //将x左移一位

2.排序

数组去重排序模板:

vector<int> a;
for(int i = 1;i <= n;i++)
    {
        int num;cin >> num;
        a.push_back(num);                           //push_back,是vector数组的方法,且vector会自动更新长度
    }
sort(a.begin(),a.end());                            //从小到大排序
a.erase(unique(a.begin(),a.end()),a.end());         //unique作用:(将a里的重复元素放到末尾并返回最后有效元素的下一位)
                                                    //erase作用: (将传入两个参数所含的部分清除掉)
for(auto &i : a) cout << i << '\n';                 //以i为索引遍历每一个数组a的元素,并将其输出
reverse(a + 1,a + 1 + n);                           //翻转a数组中的元素

遇见一个元素中有多个数据,且需要排列不同元素时,就需要使用cmp或struct;

struct book{                                        //结构体
    int a,b,c;
    bool operator < (const book &u)const{           //重载运算符
        if(u.a == a && u.b == b) return u.c < c;
        if(u.a == a) return u.b < b;
        else return u.a < a;
    }
}p[N];
​
bool cmp(const book &u,const book &v){              //cmp函数,用在sort(a.begin(),a.end(),cmp)
    if(u.a == v.a && u.b == v.b) return u.c > v.c;
    if(u.a == v.a) return u.b > v.b;
    else return u.a > v.a;
}

3.双指针

1.只往一个方向走

2.一快一慢

3.在区间内

4.二分

while(l + 1 != r)
        {
            mid = (l + r) >> 1;
            if(a[mid] < x) l = mid;
            else r = mid;
        }

C++中各类函数和方法的用法

1.bitset

bitset<n>(x) //将x转换为n进制数

2.vector

vector<int> a;             //可以自动维护数组长度,适合用在增删查改数组上vector中的方法:
    a.push_back(n)         //将放入a的最后一位
    a.begin()              //代指a的第一个数据的位置
    a.end()                //代指a的最后一个数据的位置
    a.erase(x,y)           //将a中的x——y范围的数据全部删除,此时vector会自动维护长度
    a.pop_back()           //将a中的最后一个元素清除

3.reverse

reverse(x,y);                   //翻转数组中范围为x——y的元素

4.memset

memset(c, 0 ,sizeof(int) * (n + 1) ); //将c中在n+1之前的所有元素更改为0

5.abs()

求绝对值

6.sort()

排序

1.两点间距离

sqrt( pow( abs(x1-x2) ,2 ) + pow( abs(y1-y2) ) , 2 )    //sqrt()开平方根
                                                        //pow(x,y) 得到x的y次方
也可以:sqrt( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) )        //abs() 得到参数的绝对值

2.求质数

// x = a * b  ->  min(a,b) <=sqrt(x)
int chk(int x){
    for(int i = 2;i * i <= x;++i){
        if(x % i == 0){
            return 0;
        }
    }
    return 1;
}

3.对数组进行重复且不叠加的修改时

1.可以令数组全为0,令被修改的数为1
    eg: int a[n] = {0};
                i符合条件: a[i] = 1
2.可以用bool 定义数组
    eg:  bool a[n];
                i符合条件:a[i] = 1;