【题目记录】——牛客练习赛87


题目集地址 牛客练习赛87
个人赛 制作出一题A

A 中位数 思维

题目地址A 中位数
思路:要使中位数最小,只需要每次选择数字的时候选择最大的两位即可,因为每操作一次就删除一个数,那么每次的中位数只需要是 (n-k+1)/2即可。当n-k等于1时属于特例,输出所有数的和。
AC代码:

/*
**Author:skj
**Time:
**Function:
*/
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N = 2e5+5;
int a[N];
int main()
{
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll sum = 0;
        int n, k;
        scanf("%d%d",&n,&k);
        for(int i = 1;i <= n;i++)
        {
            scanf("%d",a+i);
            sum += a[i];
        }
        if(n-k>1)
        {
            sort(a+1,a+n+1);
            printf("%d\n",a[(n-k+1)/2]);
        }
        else
        {
            printf("%lld\n",sum);
        }
    }
    return 0;
}

B k小数查询 可持久化线段树

题目地址B k小数查询
思路:由于 a 1 , a 2 , . . . , a n {a_1,a_2,...,a_n} a1,a2,...,an是{1,2,…,n}的排列,所以x只出现一次。设x所在的位置为pos,令 l i l_i li为[i,pos−1]中小于x的数的个数,r[i]为[pos+1,i]中小于x的个数。答案为 ∑ i = 1 p o s − 1 ∑ j = p o s + 1 n [ l i + r j = k − 1 ] + ∑ i = 1 p o s − 1 [ l i = = k ] + ∑ i = p o s + 1 [ r i = = k ] + [ k = = 1 ] {\sum\limits_{i=1}^{pos-1}\sum\limits_{j=pos+1}^n[l_i+r_j=k-1]}+\sum\limits_{i=1}^{pos-1}[l_i==k]+\sum\limits_{i=pos+1}[r_i==k]+[k==1] i=1pos1j=pos+1n[li+rj=k1]+i=1pos1[li==k]+i=pos+1[ri==k]+[k==1]用一个桶来计数 r i r_i ri,枚举 l i l_i li即可。
被题目给骗了,我以为是要用可持久化线段树。
AC代码:

#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int N = 2e5+5;
int a[N];
int l[N];
int r[N],rn[N];
int main()
{
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int n, x, k;
	scanf("%d%d%d",&n,&x,&k);
	int pos = N;
	for(int i = 1;i <= n;i++)
    {
        scanf("%d",a+i);
        if(a[i]==x)
        {
            pos = i;
        }
        if(i > pos)
        {
            if(a[i] < x)
            {
                r[i] = r[i-1]+1;
                rn[r[i]]++;
            }
            else
            {
                r[i] = r[i-1];
                rn[r[i]]++;
            }
        }
    }
    ll ans = 0;
    for(int i = pos-1;i >= 1;i--)
    {
        if(a[i] < x)
        {
            l[i] = l[i+1]+1;
        }
        else
        {
            l[i] = l[i+1];
        }
        if(l[i] == k-1)
        {
            ans += (rn[0]+1);
        }
        else if(l[i] < k-1)
        {
            ans += rn[k-1-l[i]];
        }
    }
    ans += rn[k-1];

    printf("%lld\n",ans);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值