1、双指针
模板
标和
for (int i = 0, j = 0; i < n; i ++ )
{
while (j < i && check(i, j)) j ++ ;
// 具体问题的逻辑
}
常见问题分类:
(1) 对于一个序列,用两个指针维护一段区间
(2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作
最长不重复子序列
#include<iostream>
using namespace std;
const int N = 100010;
int a[N], s[N];
int main()
{
int n, res = 0;
cin >> n;
for(int i = 0; i < n; ++i) cin >> a[i];
for(int i = 0, j = 0; i < n; ++i)
{
s[a[i]]++;
while(j <= i&& s[a[i]] > 1)
{
s[a[j]]--;
j++;
}
res = max(i - j + 1, res);
}
cout << res;
return 0;
}
2、位运算
求n的第k位数字: n >> k & 1
返回n的最后一位1:lowbit(n) = n & -n
//lowbit样例 lowbit(10111100000) = 100000
3、离散化
模板
vector<int> alls; // 存储所有待离散化的值
sort(alls.begin(), alls.end()); // 将所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end()); // 去掉重复元素
// 二分求出x对应的离散化的值
int find(int x) // 找到第一个大于等于x的位置
{
int l = 0, r = alls.size() - 1;
while (l < r)
{
int mid = l + r >> 1;
if (alls[mid] >= x) r = mid;
else l = mid + 1;
}
return r + 1; // 映射到1, 2, ...n
}
作者:yxc
链接:https://www.acwing.com/blog/content/277/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int n, m;
vector<int> alls;
vector<pair<int, int>> add, query;
const int N = 3*1e5 + 10;
int a[N], s[N];
int find(int x)
{
int l = 0, r = alls.size() - 1;
while(l < r)
{
int mid = l + r >> 1;
if(alls[mid] >= x) r = mid;
else l = mid + 1;
}
return l + 1;
}
int main()
{
cin >> n >> m;
//坐标值插入
for(int i = 1; i <= n; ++i)
{
int x, c;
cin >> x >> c;
add.push_back({x, c});
alls.push_back(x);
}
//区间插入
for(int i = 1; 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());
//映射到1-alls.size()
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);
int r = find(item.second);
cout << s[r] - s[l-1] << endl;
}
return 0;
}
4、区间合并
模板
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;
}
作者:yxc
链接:https://www.acwing.com/blog/content/277/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
vector<pair<int, int>> segs;
vector<pair<int, int>> merge(vector<pair<int, int>> &segs)
{
int st = -2e9, ed = -2e9;
vector<pair<int, int>> res;
sort(segs.begin(), segs.end());
for(auto item:segs)
{
if(ed < item.first)
{
if(st!=-2e9) res.push_back({st, ed});
st = item.first;
ed = item.second;
}
else ed = item.second;
}
res.push_back({st, ed});
return res;
}
int main()
{
int n;
cin >> n;
//值输入
for(int i = 0; i < n; ++i)
{
int l, r;
cin >> l >> r;
segs.push_back({l, r});
}
auto res = merge(segs);
cout << res.size();
return 0;
}