牛客练习赛87

A-中位数#

传送门

题意#

给定一个长度为n的数组,我们进行k次操作
每次操作的定义如下:

  • 选择两个下标ij 我们可以令ai=ai+aj,然后删除aj
    求操作之后的数组的中位数的最小值len+12 (len为操作后的数组长度

分析#

基于贪心的思想, 对于一个有序数组,我们可以如果通过删数使得数组的中位数最小的话,我们肯定是要尽可能的
把比较大的数字删去.
然后我们考虑删完一个数字造成的结果,使另一个数字加上这个数字.
分两种情况

  • len2 的时候,我们可以使从第n-k+1大的数字开始删,之后的数字全部删去,使他们累加到第
    n-k个数字上, 此时我们可以发现中位数永远不可能是第n-k个数字 因此我们输出 a[(len+1)/2]即可
  • len=1的时候,我们可以发现我们删去的所有数字都会累加到仅剩的这个数字上,因此我们输出所有数字的和即可
  • len=0 输出 0 即可

AC_CODE#

#include <bits/stdc++.h>

using namespace std;
 
template < typename T >
inline void read(T &x)
{
    x = 0; bool f = 0; char ch = getchar();
    while(!isdigit(ch)){f ^= !(ch ^ 45);ch=getchar();}
    while(isdigit(ch)) x= (x<<1)+(x<<3)+(ch&15),ch=getchar();
    x = f ? -x : x;
}

const int N = 2e5 + 10;
int a[N];

void solve() {
    int n, k;
    read(n), read(k);
    LL ans = 0;
    for(int i = 1; i <= n; i ++ ) {
        read(a[i]);
        ans += a[i];
    }
    sort(a + 1, a + 1 + n);
    int res = n - k; // 长度
    if(res >= 2)
        cout << a[(res + 1) / 2] << endl;
    else {
        if(res == 0) cout << 0 << endl;
        else if(res == 1) cout << ans << endl;
    }
}
 
signed main() 
{
    int T = 1;  scanf("%d",&T);
    while(T -- ) {
        solve();
    }
    return 0;
}

B-k小数查询#

题意#

给定一个1-n的任意排列, 求出所有的区间[l,r] (rl+1k) 满足
区间内第k小数是x

思路#

x肯定属于所有的满足条件的区间 (假设x的下标为idx
我们可以把区间分为三种
我们可以记li[i,idx1]区间内小于x的数字的数量 ri[idx+1,,i] 区间内小于x的数量

  • idx 为右边界的区间 所有的li=k1的点的个数
  • idx 为左边界的区间 所有的ri=k1的点的个数
  • idx为区间内某点且不是边界的区间 所有的li+ri=k1的点对

AC_CODE#

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 2e5 + 10;
int a[N], ct[N];
int n, x, k, idx;

void solve() {
    scanf("%d%d%d", &n, &x, &k);
    k --;
    for(int i = 0; i < n; i ++ ) {
        scanf("%d", &a[i]);
        if(a[i] == x) idx = i;
    }
    LL ans = 0, cnt = 0;
    for(int i = idx + 1; i < n; i ++ ) {
        cnt += a[i] < x;
        ans += cnt == k;
        ct[cnt] ++;
    }
    cnt = 0;
    for(int i = idx - 1; ~i; i --) {
        cnt += a[i] < x;
        ans += cnt == k;
        if(cnt <= k) ans += ct[k - cnt];
    }
    printf("%lld", ans);
}
 
signed main() 
{
    int T = 1; //scanf("%d",&T);
    while(T -- ) {
        solve();
    }
    return 0;
}
posted @   ccz9729  阅读(81)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩