感谢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,mid−1]和[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;
}
区间合并
合并交集
- 左端点排序
- 扫描区间,合并
#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;
}