POJ-3579 Median---二分第k大(二分套二分)
2024-10-06 14:18:29
题目链接:
https://cn.vjudge.net/problem/POJ-3579
题目大意:
求的是一列数所有相互之间差值的序列的最中间的值是多少。
解题思路:
可以用二分套二分的方法求解第m大,和POJ-3685类似,这里的模板也差不多
枚举第m大x,判断小于等于x的数目是不是大于m,如果大于m说明x >= 第m大,调整区间r = mid - 1
不然l = mid + 1
此处是大于m而不是小于m是因为一个数可能出现多次,那么小于等于中间的数目可能就比m大
在计算小于等于x的数目的时候,用upperlower函数求解即可
一开始TLE是因为左右区间没选好,应该选给定的数字中的最大值减最小值作为右区间
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const ll INF = 1e9 + ;
const int maxn = 1e6 + ;
ll a[maxn], n, m; ll ok(ll mid)
{
ll ans = ;
for(int i = ; i < n; i++)//此处不等于n是由于到了n没有比它更大的了,加上=也无妨
{
if(a[i] + mid >= a[n])//可以加速一点
{
ans += n - i;
continue;
}
int t = upper_bound(a + i, a + n + , a[i] + mid) - a;//这里用区间a+i而不是a+1可以加速求解
ans += t - - i;
}
return ans;
}
int main()
{
while(scanf("%lld", &n) != EOF)
{
for(int i = ; i <= n; i++)scanf("%lld", &a[i]);
sort(a + , a + n + );
m = n * (n - ) / ;
m = (m + ) / ;//求出第m个
ll l = , r = a[n] - a[], ans;
while(l <= r)
{
ll mid = (l + r) / ;
if(ok(mid) >= m)//小于等于mid的数字个数 >= m 说明mid>=最优解
{
ans = mid;
r = mid - ;
}
else l = mid + ;
}
printf("%lld\n", ans);
}
return ;
}
最新文章
- 基于命令行编译打包phonegap for android应用 分类: Android Phonegap 2015-05-10 10:33 73人阅读 评论(0) 收藏
- 解决PHP大文件上传问题
- 算法与数据结构之交换(SWAP)排序
- C++内嵌汇编代码,简单文件加密
- Java 8 VM GC Tunning Guild Charter 9-b
- SQL练习之求解填字游戏
- php 将pdf转成图片且将图片拼接
- x86汇编语言实践(2)
- FX-玩列表
- 从函数式编程到Ramda函数库(二)
- Docker简单使用
- Setting Tomcat Heap Size (JVM Heap) in Eclipse
- [洛谷P1731][NOI1999]生日蛋糕(dfs)(剪枝)
- Redis的使用(待更新)
- 深度学习原理与框架-Tensorflow卷积神经网络-神经网络mnist分类
- springboot 整合redis redis工具类
- hive外部表删除遇到的一个坑
- python操作mysql数据库实现增删改查
- 5 -- Hibernate的基本用法 -- 要点
- linux Valgrind使用说明-内存泄漏