F. Longest Strike
题目大意:
一个长度为n的数组和整数k。找出在数组内存在最长的 r - l,【l,r】,其中l <= ai <= r ,且存在至少k次。
解题思路: 双指针。
void solve() {
int n,k; cin>>n>>k;
map<int,int> mii; // 用map存入元素,和元素存在个数
int inp;
rep(i,1,n) {
cin>>inp;
mii[inp] ++;
}
vector<PII> vpii; // 存入pair<int,int>
for(auto t: mii) vpii.push_back({t.first, t.second});
PII lr({-1,-1}); // 结果l、r
int len = vpii.size();
// 双指针
for(int i = 0, j = 1; i < len;) {
if(vpii[i].second < k) { // 元素小于k,跳过
i++; ++j; continue;
}
while( j < len && vpii[j].first == vpii[j-1].first + 1 && vpii[j].second >= k) ++j; // 存在,找边界r
--j;
if(lr.second - lr.first <= vpii[j].first - vpii[i].first) // 长度超过原来长度,存入
lr = {vpii[i].first, vpii[j].first};
i = ++j; ++j; // 令i等于不相等的下一个元素,j为i的下一个。
}
if(lr.first == -1) puts("-1");
else cout<<lr.first<<" "<<lr.second<<"\n";
}
G. 2^Sort
题目大意:
数组长度为n,整数k。求有多少个长度为k+1,同时满足
解题思路: 双指针。首先对满足公式进行化简,即前面元素小于后面元素的二倍才可以时不等式成立。就是简单的双指针算法。
void solve() {
int n,k; cin>>n>>k;
memset(a, 0, sizeof(a));
rep(i,1,n) {
cin>>a[i];
}
int cnt = 0;
for(int i = 1, j = 2; i <= n; ) { // 双指针
int z = k; // 遍历z = k 次;
while(j <= n && a[j]*2 > a[j-1] && z) j++, z--; // 每次遍历,z--,快指针++
if(!z) { // 如果z == 0,表示成立一个
cnt++;
while(j <= n && a[j]*2 > a[j-1]) j++, cnt++; // while循环求满足k+1区间还有多少个
}
i = j, ++j; // 不满足,慢指针等于快指针,快指针++,从新开始
}
cout<<cnt<<endl;
}
F. Yet Another Problem About Pairs Satisfying an Inequality
题目大意:
给一数组,求 有多少个满足要求的i、j。
解题思路: 首先,剔除永远不可能的元素,即 ai > i 的元素。可以将满足 ai < i 的元素的 ai 和 i 分别存入不同的数组中,通过在i 下标的数组中二分aj,找到有多少个i < aj 的元素,累加即可。
void solve() {
int n; cin>>n;
vector<int> viArr, vii;
rep(i,1,n) {
cin>>a[i];
// 满足要求,将 a[i] i 分别存入数组中
if(a[i] < i) viArr.push_back(a[i]), vii.push_back(i);
}
LL ans = 0; // 答案 long long
int len = vii.size();
rep(i,0,len-1) {
// 在 满足要求的i数组中找有多少个元素满足 i < aj 的要求
ans += lower_bound(vii.begin(), vii.end(), viArr[i]) - vii.begin();
}
cout<<ans<<endl;
}
总结
这次专门做了几道双指针算法的题。感觉有种说不上来的感觉,看到
tag-双指针的题会写,但是平时没有tag提示时是怎么也想不到双指针算法。感觉这个双指针还是要再多练,跟自己之前学的不一样。
第三题的二分也是,代码短短的,就是不好想,我刚开始想用dp,发现第一个样例就有逻辑问题。这题用二分认为实在是太妙了。
有些题,还是要根据题意进行简化问题。 第二题就是属于这种,每次乘2的倍数,不简化真不好写。
今天重新温故了algorithm库的lower_bound, upper_bound函数。返回值是满足要求的第一个元素的指针。 lower_bound(a) - a.begin 是满足要求的第一个元素的下标位置,-之前好像都记错了,记成有多少个不满足要求的了。