Haybale Stacking(差分数组 + 求中位数的一些方法 + nth_element)
题意:
给定N个初始值为0的数, 然后给定K个区间修改(区间[l,r] 每个元素加一), 求修改后序列的中位数。
分析:
K个离线的区间修改可以使用差分数组(http://www.cnblogs.com/Jadon97/p/8053946.html)实现。
关于对一个无序的序列找出中位数
方法一:
第一时间想到的方法是快排然后之间取中位数, 排序复杂度为O(NlogN),取第k大的数复杂度O(1)。
用时:124ms
#include <bits/stdc++.h>
using namespace std;
const int maxn = + ;
int N, K;
int a[maxn], d[maxn];
int main(){
cin >> N >> K;
d[] = a[];
for(int i = ; i < K; i++){
int a, b;
cin >> a >> b;
d[a]++, d[b+]--;
}
for(int i = ; i <= N; i++){
a[i] = a[i-] + d[i];
}
sort(a+,a++N);
cout << a[N/+] << "\n";
return ;
}
快排
方法二:
但其实还有有一个O(n)的算法,是利用快排的思想,详情可查看partiton算法(http://blog.jobbole.com/105219/),这个算法可以延伸到求第k大的数
- pos == k,则找到第 K 小的值,arr[pos];
- pos > k,则第 K 小的值在左边部分的数组。
- pos < k,则第 K 大的值在右边部分的数组。
而在最好情况下,每次将数组均分为长度相同的两半,运行时间 T(N) = N + T(N/2),时间复杂度是 O(N), 但是这个算法最坏情况是O(N²),暂时没想到很好的优化方法。
#include<bits/stdc++.h>
using namespace std;
const int maxn = + ;
int N, K;
int a[maxn], d[maxn];
int partition(int begin, int end) //[begin,end]左闭右闭区域
{
int pivot = a[begin];//选取第一个数为枢轴
while(begin < end)
{
while(begin < end && a[end] >= pivot) end--; //在后面选取一个小于枢轴的数
a[begin] = a[end]; //将那个数放到前面
while(begin < end && a[begin] <= pivot) begin++; //在前面选取一个大于枢轴的数
a[end] = a[begin];//将那个数放到后面
}
a[begin] = pivot;//最后将枢轴放回
return begin;//返回枢轴的下标
} int find_kth_number(int k){
int begin = , end = N;
int target_num = ;
while (begin <= end){
int pos = partition(begin, end);//查看枢轴的位置
if(pos == k){//如果枢轴 == k, 那么枢轴就是第k小的数
target_num = a[pos];
break;
}
else if(pos > k){//否则从左边找
end = pos - ;
}
else{//否则从右边找
begin = pos + ;
}
}
return target_num;
}
int main(){
scanf("%d %d", &N, &K);
d[] = a[];
for(int i = ; i < K; i++){
int a, b;
scanf("%d %d", &a, &b);
d[a]++, d[b+]--;
}
for(int i = ; i <= N; i++){
a[i] = a[i-] + d[i];
}
printf("%d\n", find_kth_number(N/+));
return ;
}
parition算法
但是有一个STL库函数eth_element(http://zh.cppreference.com/w/cpp/algorithm/nth_element), 思想应该是差不多的, 但因为优化原因运行时间可以过这题, 所以可以使用这个库函数快速求出第k大的数。
用时:74ms
#include <bits/stdc++.h>
using namespace std;
const int maxn = + ;
int N, K;
int a[maxn], d[maxn];
int main(){
scanf("%d %d", &N, &K);
d[] = a[];
for(int i = ; i < K; i++){
int a, b;
scanf("%d %d", &a, &b);
d[a]++, d[b+]--;
}
for(int i = ; i <= N; i++){
a[i] = a[i-] + d[i];
}
nth_element(a+,a+N/+,a++N);
printf("%d\n", a[N/+]);
return ;
}
nth_element
方法三:
对于这题特殊的区间修改, 因为N多达1e6, 而K只有25000, 所以最大的数也只有K, 所以我们求出区间修改的值的时候,可以把每个数的出现次数记录下来, 然后循环K次,把出现次数累计起来。加上某个数累计次数大于等于N/2时, 那个数就是中位数,复杂度是(N+K),应该是最快的方法了。
用时:49ms
#include <bits/stdc++.h>
using namespace std;
const int maxn = ;
int N, K;
int a[maxn], d[maxn];
int cnt_num[ + ];
int main(){
scanf("%d %d", &N, &K);
d[] = a[];
for(int i = ; i < K; i++){
int a, b;
scanf("%d %d", &a, &b);
d[a]++, d[b+]--;
}
for(int i = ; i <= N; i++){
a[i] = a[i-] + d[i];
cnt_num[a[i]]++;//统计每个数字出现了多少次
}
int sum = , mid_num;
for(mid_num = ; mid_num <= K; mid_num++){
sum += cnt_num[mid_num];
if(sum > N/) break;
}
printf("%d\n", mid_num);
return ;
}
统计数字
Haybale Stacking(差分数组 + 求中位数的一些方法 + nth_element)的更多相关文章
- 三个数组求中位数,以及中位数的中位数----java算法实现
求三个数组的中位数,以及中位数的中位数. import java.util.Arrays; public class median { public static void main(String ...
- 1005E1 Median on Segments (Permutations Edition) 【思维+无序数组求中位数】
题目:戳这里 百度之星初赛原题:戳这里 题意:n个不同的数,求中位数为m的区间有多少个. 解题思路: 此题的中位数就是个数为奇数的数组中,小于m的数和大于m的数一样多,个数为偶数的数组中,小于m的数比 ...
- 两个有序数组求中位数log(m+n)复杂度
leetcode 第4题 中位数技巧: 对于长度为L的有序数组,它的中位数是(a[ceil((L+1)/2)]+a[floor((L+1)/2)])/2 算法原理: 类似三分法求极值 两个人都前进,谁 ...
- LeetCode第[4]题(Java):Median of Two Sorted Arrays (俩已排序数组求中位数)——HARD
题目难度:hard There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median ...
- 三个数组求中位数,并且求最后中位数的中位数-----C++算法实现
文件Median.h #include <list> class CMedian { public: explicit CMedian(); virtual ~CMedian(); voi ...
- [nowCoder] 两个不等长数组求第K大数
给定两个有序数组arr1和arr2,在给定一个整数k,返回两个数组的所有数中第K小的数.例如:arr1 = {1,2,3,4,5};arr2 = {3,4,5};K = 1;因为1为所有数中最小的,所 ...
- LeetCode题目----求中位数---标签:Array
题目难度---困难 题目要求: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2 . 请找出这两个有序数组的中位数.要求算法的时间复杂度为 O(log (m+n)) . 思路:第一眼 ...
- leetcode题目4.寻找两个有序数组的中位数(困难)
题目描述: 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2. 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n)). 你可以假设 nums1 和 ...
- [NOIP2013提高&洛谷P1966]火柴排队 题解(树状数组求逆序对)
[NOIP2013提高&洛谷P1966]火柴排队 Description 涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
随机推荐
- 给Clouderamanager集群里安装基于Hive的大数据实时分析查询引擎工具Impala步骤(图文详解)
这个很简单,在集群机器里,选择就是了,本来自带就有Impala的. 扩展博客 给Ambari集群里安装基于Hive的大数据实时分析查询引擎工具Impala步骤(图文详解)
- Java | 基础归纳 | set
用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复.
- Hdu 3652 B-number (同余数位DP)
题目链接: Hdu 3652 B-number 题目描述: 给出一个数n,问 [1, n]区间内有几个数能被13整除并且还有13这个子串? 解题思路: 能整除的数位DP,确定好状态随便搞搞就能过了.d ...
- 高阶函数之filter 和 sorted
filter函数 接受一个函数和序列,把传入的函数依次作用于每个序列,然后根据返回值时True还是False保留或舍弃元素. def func(n): if n%2 == 0: return n m ...
- JS进阶-特殊形式的函数-内部私有函数
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 微信小程序 图片加载失败处理方案
小程序端展示网络资源图片可能会失败,下面介绍一种自己的处理方法 1. js文件中判断图片 url 是否存在,存在则正常显示,不存在则替换url为本地默认图片 2. 当图片 url 存在,但是加载失败时 ...
- Math.net,.net上的科学计算利器
F#在科学计算领域的应用,包括部分语法介绍. Math.net,.net上的科学计算利器 摘要: .net上科学计算个人觉得首选numpy和scipy for dotnet.因为这两个库用户数量已经非 ...
- Bundle的用法
一.API文档说明 1.介绍 用于不同Activity之间的数据传递 1.重要方法 clear():清除此Bundle映射中的所有保存的数据. clone():克隆当前Bundle containsK ...
- android xml中使用include标签
在一个项目中,我们可能会在xml中局部用到相同的布局,如果每次都在xml中重写这些布局,代码显得很冗余.重复的复制黏贴也很烦恼,所以,我们把这些相同的局部布局写成一个单独的xml模块,需要用到这些布局 ...
- Qt和Cocoa混合编程
https://el-tramo.be/blog/mixing-cocoa-and-qt/