蓝桥杯C++大学B组一个月冲刺记录2024/3/5

蓝桥杯C++大学B组一个月冲刺记录2024/3/4

规则:每日三题

1.牛的学术圈

由于对计算机科学的热爱,以及有朝一日成为 「Bessie 博士」的诱惑,奶牛 Bessie 开始攻读计算机科学博士学位。
经过一段时间的学术研究,她已经发表了 N篇论文,并且她的第 i 篇论文得到了来自其他研究文献的 ci次引用。
Bessie 听说学术成就可以用 h指数来衡量。
h指数等于使得研究员有至少 h篇引用次数不少于 h的论文的最大整数 h。
例如,如果一名研究员有 4篇论文,引用次数分别为 (1,100,2,3),则 h指数为 2,然而若引用次数为 (1,100,3,3)则 h指数将会是 3。
为了提升她的 h指数,Bessie 计划写一篇综述,并引用一些她曾经写过的论文。
由于页数限制,她至多可以在这篇综述中引用 L篇论文,并且她只能引用每篇她的论文至多一次。
请帮助 Bessie 求出在写完这篇综述后她可以达到的最大 h指数。

可以使用双指针
但我更喜欢二分

#include<iostream>
#include<cstdio>
#include<algorithm>

using namespace std;

const int M = 1e5+10;

int p[M];
int n,k;

bool check(int mid){
    int q = k;
    int tot = 0;

    for(int i = 1;i <= n;++i){
        
        if(mid - p[i] == 1&&q != 0){
           q--;
           tot++;
        }
        if(p[i] >= mid) tot ++;
    }

    if(tot >= mid) return true;
    else return false;

}

int main(){
    cin >> n >> k;

    int l = 0,r = 1e5;

    for(int i = 1;i <= n;++i){
        cin >> p[i];
    }

    while(l < r){
        int mid = (l + r + 1)/2;
        if(check(mid) == false) r = mid - 1;
        else l = mid;
    }

    cout << l << endl;


    return 0;


}

2.最长连续不重复子序列

给定一个长度为 n的整数序列,请找出最长的不包含重复的数的连续区间,输出它的长度。

双指针

#include<iostream>
#include<algorithm>

using namespace std;
const int M = 1e5+5;

int p[M],num[M];

int n;

int ans = -1;

int main(){
   cin >> n;

   for(int r = 1,l = 1;r <= n;++r){
      cin >> p[r];
      num[p[r]]++;

      while(num[p[r]] > 1){
         num[p[l]]--;
         l++; 
      }

      ans = max(r - l + 1,ans);
   }

   cout << ans << endl;

   return 0;
}

3.数组元素的目标和

给定两个升序排序的有序数组 A和 B,以及一个目标值 x。
数组下标从 0开始。
请你求出满足 A[i]+B[j]=x的数对 (i,j)。
数据保证有唯一解。

二分做法

#include<iostream>
#include<cstdio>

using namespace std;

const int M = 1e5+10;

int a[M],b[M];

int n,m,k;

int find(int t){
   int l = 1,r = n;

   while(l < r){
      int mid = (l + r + 1)/2;
      if(a[mid] > t) r = mid - 1;
      else l = mid; 
   }

   if(a[l] == t) return l;
   else return -1;
}
int main(){
    cin >> n >> m >> k;

    for(int i = 1;i <= n; ++i) cin >> a[i];
    

    for(int j = 1;j <= m; ++j){
      cin >> b[j];
      int t = find(k - b[j]);
      if(t != -1){
         cout << t - 1 << ' ' << j - 1 << endl;
         return 0;
      }
    }

    return 0;
}

双指针做法

#include<iostream>

using namespace std;

const int N =1e5+10;
int a[N],b[N];

int main(){
    int n,m,x;
    cin >> n >> m >> x;
    
    for(int i = 1;i <= n;++i) cin >> a[i];
    for(int j = 1;j <= m;++j) cin >> b[j];
    
    for(int i = 1,j=m;i<=n;++i){
        while(j>=0&&a[i]+b[j] > x) j--;
        if(a[i] + b[j] == x){
            cout << i-1 <<' '<< j-1 << '\n'; 
            break;
        }
    }
    
    return 0;
    
}

4.判断子序列

给定一个长度为 n的整数序列 a1,a2,…,an以及一个长度为 m 的整数序列 b1,b2,…,bm。
请你判断 a序列是否为 b序列的子序列。
子序列指序列的一部分项按原有次序排列而得的序列,例如序列 {a1,a3,a5}是序列 {a1,a2,a3,a4,a5}的一个子序列。

双指针

#include<iostream>
#include<cstdio>

using namespace std;

const int M = 1e5+10;

int a[M],b[M];

int n,m;

int main(){
    cin >> n >> m;

    for(int i = 1;i <= n; ++i) cin >> a[i];
    for(int j = 1;j <= m; ++j) cin >> b[j];

    for(int l = 1, r =  1;r <= m; ++r){
        if(a[l] == b[r]) l++;

        if(l > n){
            cout << "Yes" << endl;

            return 0;
        }
    }


    cout << "No" << endl;

    return 0;  
}

5.日志统计

小明维护着一个程序员论坛。现在他收集了一份”点赞”日志,日志共有 N
行。
其中每一行的格式是:ts id 表示在 ts时刻编号 id的帖子收到一个”赞”。
现在小明想统计有哪些帖子曾经是”热帖”。
如果一个帖子曾在任意一个长度为 D的时间段内收到不少于 K个赞,小明就认为这个帖子曾是”热帖”。
具体来说,如果存在某个时刻 T满足该帖在 [T,T+D)这段时间内(注意是左闭右开区间)收到不少于 K个赞,该帖就曾是”热帖”。
给定日志,请你帮助小明统计出所有曾是”热帖”的帖子编号。

双指针
第一遍做的时候,用vector存数据,循环的是时间的区间,用 i,j 去记录加入的记录和删去的记录下标。但是vector< PII > 会出现段错误

#include<iostream>
#include<algorithm>

using namespace std;

const int M = 1e5+10;

typedef pair<int,int>PII;

PII p[M];
int res[M],st[M];

int n,d,k;
int main(){
    cin >> n >> d >> k;

    for(int i = 1;i<=n;++i){
        cin >> p[i].first >> p[i].second;
    }

    sort(p + 1,p + n + 1);
    
    for(int i = 1,j = 1;i <= n; ++i){
        
        res[p[i].second] ++;

        while(p[i].first - p[j].first >= d){
            res[p[j].second] --;
            j++;
        }

        if(res[p[i].second] >= k) st[p[i].second]++;
    }

    for(int i = 0;i <= 1e5;++i){
        if(st[i] != 0) cout << i << endl;
    }


    return 0;

}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值