cf*3 总结与反思

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 是满足要求的第一个元素的下标位置,-之前好像都记错了,记成有多少个不满足要求的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

golemon.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值