【算法】基础算法

感谢acwing,学习的过程是有趣的

排序

快排

分治思想
在这里插入图片描述

归并

在这里插入图片描述

在这里插入图片描述

二分

整数二分

lower_bound( begin,end,num)
从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标
upper_bound( begin,end,num )
从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。
感觉这个蛮重要的
[ l , m i d ] 和 [ m i d + 1 , r ] [l, mid] 和 [mid+1,r] [l,mid][mid+1,r]
[ l , m i d − 1 ] 和 [ m i d , r ] — — m i d = r + l + 1 > > 2 [l, mid-1] 和 [mid, r]——mid=r+l+1 >>2 [l,mid1][mid,r]mid=r+l+1>>2
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

高精度

位数: 1 0 6 10^6 106大整数相加/-/*
auto:编译器自己推断变量类型

大整数+

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

前缀和

一维前缀和

S 0 = 0 S_0=0 S0=0
在这里插入图片描述
在这里插入图片描述

二维前缀和

在这里插入图片描述

差分

一维差分

已知 a 1 , a 2 , a 3 . . . a n a_1, a_2, a_3 ... a_n a1,a2,a3...an
构造 b 1 , b 2 , b 3 . . . b n b_1, b_2, b_3 ... b_n b1,b2,b3...bn,使得 a i = b 0 + . . . b i a_i=b_0+...b_i ai=b0+...bi,A是B的前缀和
在这里插入图片描述

二维差分

在这里插入图片描述
在这里插入图片描述

双指针

优化 O ( n 2 ) − O ( n ) O(n^2)-O(n) O(n2)O(n)
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

位运算

在这里插入图片描述

n的二进制表示中的第K位
先把第K位移到最后一位

n >> k  先把第K位移到最后一位 
        看n的个位
lowbit(x) 返回最后一位1
x&-x = x&(~x+1)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

离散化

稀疏,映射
排了序之后下标就是映射的值
在这里插入图片描述

#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;
typedef pair<int,int> PII;//记录插入的两个变量的值

const int N = 300000+10;//30w是10w条插入与查询的最大数组

int n,m;//n次插入,m次查询操作
int a[N],s[N];//a[N] 离散化数组,s[N]前缀和

vector<int> alls;//
vector<PII> add,query;

int find(int x){//二分查找,映射到1-n 因此r+1
    int l=0,r=alls.size()-1;
    while(l<r){
        int mid = r+l>>1;
        if(alls[mid]>=x) r=mid;
        else l=mid+1;
    }
    return r+1;
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        int x,c;
        cin>>x>>c;
        add.push_back({x,c});

        alls.push_back(x);
    }
    for(int i=0;i<m;i++){
        int l,r;
        cin>>l>>r;
        query.push_back({l,r});

        alls.push_back(l);
        alls.push_back(r);

    }
    //去重
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());

    for(auto item:add){
        int x = find(item.first);
        a[x]+=item.second;
    }

    // 预处理前缀和
    for(int i=1;i<=alls.size();i++) s[i] = s[i-1]+a[i];
    // 处理询问
    for (auto item : query)
    {
        int l = find(item.first), r = find(item.second);
        cout << s[r] - s[l - 1] << endl;
    }
    return 0;
}

区间合并

合并交集

  1. 左端点排序
  2. 扫描区间,合并
#include<iostream>
#include<vector>
#include<algorithm>

using namespace std;

typedef pair<int,int> PII;


void merge(vector<PII> &segs)
{
    vector<PII> res;

    sort(segs.begin(), segs.end());

    int st = -2e9, ed = -2e9;
    for (auto seg : segs)
        if (ed < seg.first)
        {
            if (st != -2e9) res.push_back({st, ed});
            st = seg.first, ed = seg.second;
        }
        else ed = max(ed, seg.second);

    if (st != -2e9) res.push_back({st, ed});

    segs = res;
}


int main(){
    int n;
    cin>>n;
    vector<PII> segs;
    for(int i=0;i<n;i++){
        int l,r;
        cin>>l>>r;
        segs.push_back({l,r});
    }
    merge(segs);

    cout<<segs.size()<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值