找工作跟着ACWing学基础算法刷题记事本

前缀和:

#include <iostream>
using namespace std;
const int N = 100010;

int n,m;
int a[N],s[N];

int main()
{
    cin>>n>>m;
    for(int i = 1;i<=n;i++) cin>>a[i];
    for(int i = 1;i<=n;i++) s[i] = s[i-1]+a[i]; //初始化前缀和数组
    while(m--)
    {
        int l,r;
        cin>> l>>r;
        cout<<s[r]- s[l-1]<<endl;
    }
}

差分:

#include <iostream>
using namespace std;
const int N=100010;
int n,m;  //n个整数 m个操作
int a[N], b[N];
void insert(int l, int r, int c)
{
    b[l]+=c;
    b[r+1]-=c;
}

int main()
{
    cin >>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) insert(i,i,a[i]);//利用差分数组 初始化a前缀和数组 这里b数组就是a数组了 这里主要是给b数组赋值
    while(m--)
    {
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c);    //在b差分数组中加入c
    }
    for(int i=1;i<=n;i++) b[i] +=b[i-1];
    for(int i=1;i<=n;i++) cout<<b[i]<<' ';
    return 0;
}
//总体思路就是
//1.构建两个数据 a,b a是b的前缀和 b是a的差分数组 a与b之间的关系不用在意 a可以由差分数组初始化
//2.[l,r]范围内加减一个c 只需要o(1)时间复杂度 在b[l]+c b[r+1]-c 

双指针算法:不开数组的情况下只能用哈希表

#include <iostream>
using namespace std;
const int N=100100;
int n;
int q[N], s[N];  
int main()
{
    cin>>n;
    for(int i=0;i<n;i++) cin>>q[i];
    int res= 0 ;
    for(int i=0,j=0;i<n;i++)
    {
        s[q[i]]++;  
        while(s[q[i]]>1)
        {
            s[q[j]]--;     //通过开数组计数将j--->i
            j++;
        }
        res = max(res, i-j+1);
    }
    
    cout<< res;
    return 0;
}


双指针算法通常都是先写一个暴力算法然后看双指针有无单调关系,有单调关系可以将时间复杂度从O(n^2)--->O(n)。

位运算:

n的二进制表示中第k位是多少?

①先把第k位移到最后一位 n>>k

②看个位是多少 x&1

将①和②融合起来 n>>k&1。

#include <iostream>
using namespace std;

int main()
{
    int n = 10;
    for(int i =3; i>=0;i--)  cout<<(n>>i&1)<<endl;
    return 0;
}

lowbit(x):返回x的最后一位1.

比如说

x=1010       lowbit(x) = 10(二进制)

x=101000   lowbit(x) = 1000(2)

lowbit  ==  x&-x =x&(~x+1)  这里是补码的概念

#include <iostream>
using namespace std;

int lowbit(int x)
{
    return x&-x;
}
int main()
{
    int n;
    cin >> n;
    while(n--)
    {
        int i;
        cin >>i;
        int res=0;
        while(i) i-=lowbit(i), res++; //每次减去x的最后一位1
        cout<<res<<' ';
    }
    return 0 ;
}

 源码、反码和补码:

反码是源码取反;补码是源码取反+1.

位运算:

①求n的第k位数字:n>>k&1;

②返回n的最后一位1:lowbit(n)=n&-n

离散化:

//离散化
vector<int> alls; //存储所有待离散化的值
sort(alls.begin(),alls.end());//将所有值排序
alls.erase(unique(alls.begin(),alls.end()),alls.end());//去掉重复元素


//二分求出x对应的离散化的值
int find(int x)
{
    int l=0, r=alls.size()-1;
    while(l<r)
    {
        int mid = l+r >>1;
        if(mid>=x) r=mid;
        else l= mid+1;    
    }
    return r+1; //这里+1是映射到1,2...n; 不加1是映射到0,1,2,...n-1
}

  • 8
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值