牛客练习赛87
A-中位数
题意
给定一个长度为\(n\)的数组,我们进行\(k\)次操作
每次操作的定义如下:
- 选择两个下标\(i\)\(j\) 我们可以令\(a_i = a_i + a_j\),然后删除\(a_j\)
求操作之后的数组的中位数的最小值\(\lfloor \frac{len+1}{2} \rfloor\) (len为操作后的数组长度
分析
基于贪心的思想, 对于一个有序数组,我们可以如果通过删数使得数组的中位数最小的话,我们肯定是要尽可能的
把比较大的数字删去.
然后我们考虑删完一个数字造成的结果,使另一个数字加上这个数字.
分两种情况
- \(len \geq 2\) 的时候,我们可以使从第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]\) (\(r-l+1 \geq k\)) 满足
区间内第\(k\)小数是\(x\)
思路
\(x\)肯定属于所有的满足条件的区间 (假设\(x\)的下标为\(idx\))
我们可以把区间分为三种
我们可以记\(l_i\) 为 \([i,idx-1]\)区间内小于\(x\)的数字的数量 \(r_i\)为\([idx+1,,i]\) 区间内小于\(x\)的数量
- 以\(idx\) 为右边界的区间 所有的\(l_i\)=\(k - 1\)的点的个数
- 以\(idx\) 为左边界的区间 所有的\(r_i\)=\(k - 1\)的点的个数
- \(idx\)为区间内某点且不是边界的区间 所有的\(l_i + r_i = k - 1\)的点对
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;
}