一.基础算法

快速排序

void quicksort(int a[],int l,int r){
    if(l>=r) return ;
    int x=a[l+r>>1],i=l-1,j=r+1;
    while(i<j){
        do i++;while(a[i]<x);
        do j--;while(a[j]>x);
        if(i<j) swap(a[i],a[j]);
    }
    quicksort(a,l,j);
    quicksort(a,j+1,r);
}

归并排序

void mergesort(int left,int right){
    if(left>=right) return ;
    int mid=(left+right)/2;
    mergesort(left,mid);
    mergesort(mid+1,right);
    int i=left,j=mid+1,k=0;
    while(i<=mid&&j<=right){
        if(a[i]<=a[j]) b[k++]=a[i++];
        else b[k++]=a[j++];
    }
    while(i<=mid) b[k++]=a[i++];
    while(j<=right) b[k++]=a[j++];
    for(int i=left,j=0;i<=right;i++,j++) a[i]=b[j];
    return ;
}

二分

//整数二分
int left=l,right=r;
while(left<right){
    int mid=left+right>>1;
    if(check(mid)) right=mid;
    else left=mid+1;
}
int left=l,right=r;
while(left<right){
    int mid=left+right+1>>1;
    if(check(mid)) right=mid-1;
    else left=mid;
}

//浮点数二分
double l,r;
while(r-l>1e-8){
    double mid=(l+r)/2;
    if(check(mid)) l=mid;
    else r=mid;
}

高精度

A+B
vector<int> add(vector<int>&A,vector<int>&B){
    vector<int>C;
    int t=0;
    for(int i=0;i<A.size()||i<B.size();i++){
        if(i<A.size()) t+=A[i];
        if(i<B.size()) t+=B[i];
        C.push_back(t%10);
        t/=10;
    }
    if(t) C.push_back(1);
    return C;
}

A-B
vector<int> sub(vector<int> &A,vector<int> &B){
    vector<int>C;
    int t=0;
    for(int i=0;i<A.size();i++){
        t=A[i]-t;
        if(i<B.size()) t-=B[i];
        C.push_back((t+10)%10);
        if(t<0) t=1;
        else t=0;
    }
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

A*b
vector<int> mul(vector<int> &A,int b){
    vector<int>C;
    int t=0;
    for(int i=0;i<A.size()||t;i++){
        if(i<A.size()) t+=A[i]*b;
        C.push_back(t%10);
        t/=10;
    }
    return C;
}

A/b
vector<int> mul(vector<int> &A,int b,int &r){
    vector<int>C;
    r=0;
    for(int i=A.size();i>=0;i--){
        r=r*10+A[i];
        C.push_back(r/b);
        r%=b;
    }
    reverse(C.begin(),C.end());//#include<algorithm>
    while(C.size()>1&&C.back()==0) C.pop_back();
    return C;
}

前缀和与差分

一维前缀和
a[i]+=a[i-1];
表示l到r区间的元素和:
a[r]-a[l-1];

二维前缀和
a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
表示(x1,y1)到(x2,y2)区间的元素和:
a[x2][y2]+a[x1-1][y1-1]-a[x1-1][y2]-a[x2][y1-1];

一维差分
a[i]=b[i]-b[i-1];
表示将序列中[l,r]之间的每个数加上c:
a[l]+=c,a[r+1]-=c;

二维差分
b[i][j]+=a[i][j];
b[i+1][j+1]+=a[i][j];
b[i][j+1]-=a[i][j];
b[i+1][j]-=a[i][j];
表示将(x1,y1)到(x2,y2)之间每个数加上c:
b[x1][y1]+=c;
b[x2+1][y2+1]+=c;
b[x1][y2+1]-=c;
b[x2+1][y1]-=c;

双指针

for(i=0,j=0;i<n;i++){
    while(j<i&&check(i,j)) j++;
    //......
}

位运算

把n的二进制数的第k位移动到最后一位:
n>>k;
求n的二进制数的最后一位
n&1;
求n的二进制数的第k位
n>>k&1;

lowbit(x);
表示返回x表示的二进制中最低位1对应的值
如:
x为10D,则其二进制表示为1010B
则lowbit(x)=10B=2D
实现:
int lowbit(int x){
    return x&-x;
}

离散化

离散化本质上就是化大为小,把稀疏离散化简为稠密连续的一段
特点:值域大,个数少

//离散化模板:
vector<int>a;//存储所有待离散化的值
sort(a.begin(),a.end());//排序
a.erase(unique(a.begin(),a.end()),a.end());//去重
//二分出x对应的离散化的值
int find(int x){//找到第一个大于等于x的位置
    int l=0,r=a.size()-1;
    while(l<r){
        int mid=l+r>>1;
        if(a[mid]>=x) r=mid;
        else l=mid+1;
    }
    return r+1;//映射到1,2,3,4,5,6......
}

//另一种离散化模板:
void work(int a[]){
    for(int i=1;i<=n;i++) p[i]=i;
    sort(p+1,p+1+n,[&](int x,int y){return a[x]<a[y];});
    for(int i=1;i<=n;i++) a[p[i]]=i;
}

//另一种离散化模板:
补:lower_bound(first,last,value):
   可以查找区间中第一个>=value的值,返回指向这个数的下标的迭代器
   lower_bound的头文件为#include<algorithm>
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];//输入要离散化的a数组
        b[i]=a[i];//b数组临时记录a的值
    }
    sort(a+1,a+n+1);//给a排序
    int cnt=unique(a+1,a+n+1)-(a+1);//计算a中不重复的所有元素个数
    for(int i=1;i<=n;i++){
        b[i]=lower_bound(a+1,a+cnt+1,b[i])-(a+1)+1;//将b数组更新为离散化后的下标
    }
    for(int i=1;i<=n;i++) cout<<b[i]<<" ";//输出b数组
    return 0;
}

区间合并

#include<algorithm>
#define x first
#define y second
const int N=1e5+5;
typedef pair<int,int>pii;
pii seg[N];
sort(seg,seg+n);
int l=seg[0].x,r=seg[0].y;
for(int i=0;i<n;i++){
    if(seg[i].x<=r) r=max(r,seg[i].y);
    else l=seg[i].x,r=seg[i].y;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值