查找第K大的值

时间:2023-03-10 04:53:25
查找第K大的值

这种题一般是给定N个数,然后N个数之间通过某种计算得到了新的数列,求这新的数列的第K大的值


POJ3579

题意:

用$N$个数的序列$x[i]$,生成一个新序列$b$。

新的序列定义为:对于任意的$ i$,$j$且 $i != j $有$b[] = abs(x[i] - x[j])$

问新序列的中位数是什么,如果新序列的长度为偶数那么我们定义中位数为排序后第len/2位置的那个数

解法:

相当于问新序列中的第K大的数多少。

注意新数列不可能全都算出来。

二分答案,二分那个第K大的数的值。

$x[i]-x[j] \ge mid$

相当于

$x[i] \ge mid+x[j]$

然后我们在排序过的原数组中,对每个$a[i]$二分这个$mid$值,统计有多少个值小于它,统计累加所有的值,最后看是不是小于K

代码如下:

 int N;
int a[MAXN];
LL M; bool C(int t) {
LL cnt = ;
for (int i = ; i < N; i++) {
cnt += N - (lower_bound(a + i + , a + N, a[i] + t) - a);
}
return cnt <= M / ;
} void solve() {
sort(a, a + N);
M = N * (N - ) / ;
int ub = a[N - ] + , lb = ;
while (ub - lb > ) {
int mid = (ub + lb) >> ;
if (C(mid)) {
ub = mid;
} else {
lb = mid;
}
}
cout << lb << endl;
return;
} int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif // !ONLINE_JUDGE
while (~scanf("%d", &N)) {
for (int i = ; i < N; i++) {
scanf("%d", &a[i]);
}
solve();
}
return ;
}

POJ3685

题意:

有一个$ N*N$ 的矩阵$ A$ ,$A[i][j]=i^2+100000i+j^2-100000j+ij$

求所有矩阵元素中第$ K$ 大的值

解法:

求第$ K$ 大的值,二分答案

首先肯定是二分这个K值是多少,接下来就是验证的问题。

由于$ N*N$ 的值很大,所以我们必须找到它的单调性,那么有以下式子:

$A[i+1][j] = A[i][j] + (2*i + j + 1 + 100000)$(同一列递推式)

$A[i][j+1] = A[i][j] + (2*j + i + 1 - 100000)$ (同一行递推式)

可以发现:在列方向上,矩阵单调递增,而在行方向上上,当$ (2*j + i + 1)> 100000 $ 时,递增,反之递减。

那么我们在每个列方向上直接二分那个$ i$ 值的大小,判断的一句就是$ A[i][j]$ 与假想$ K$ 值的大小关系。

代码如下:

 LL N, M;

 LL cal(LL i, LL j) { return i * i +  * i + j * j -  * j + i * j; }

 bool C(LL x) {
LL sum = ;
for (int j = ; j <= N; j++) {
LL ub = N + , lb = ;
LL ans = ;
while (ub - lb > ) {
LL mid = (ub + lb) >> ;
if (cal(mid, j) <= x) {
ans = mid;
lb = mid;
} else {
ub = mid;
}
}
sum += ans;
}
return sum >= M;
} void solve() {
LL ub = LLINF, lb = -LLINF;
while (ub - lb > ) {
LL mid = (ub + lb) >> ;
if (C(mid)) {
ub = mid;
} else {
lb = mid;
}
}
cout << ub << endl;
return;
} int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif // !ONLINE_JUDGE
int T = READ();
while (T--) {
getchar();
scanf("%lld%lld", &N, &M);
solve();
}
return ;
}