前缀和:
#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
}