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 根火柴,每根火柴都有一个高度. 现在将每盒中的火柴各自排成一列, 同一列火柴的高度互不相 ...
随机推荐
- Jamie and Interesting Graph CodeForces - 916C
http://codeforces.com/problemset/problem/916/C 好尬的题啊... #include<cstdio> #include<algorithm ...
- Subsequence HDU - 3530
Subsequence HDU - 3530 方法:单调队列区间最大最小 错误记录(本地写错)的原因:写成每次试着扩展右端点,却难以正确地处理"在多扩展右端点之后减去多扩展的部分" ...
- Codeforces Round #323 (Div. 2)
被进爷坑了,第二天的比赛改到了12点 水 A - Asphalting Roads /************************************************ * Author ...
- BestCoder Round #54 (div.2) 1003 Geometric Progression
题目传送门 题意:判断是否是等比数列 分析:高精度 + 条件:a[i] * a[i+2] == a[i+1] * a[i+1].特殊情况:0 0 0 0 0是Yes的,1 2 0 9 2是No的 代码 ...
- c库函数-字符串
一 strok:从字符串中按照分隔符提取所有字串 char s[] = "水发产品,47.6,不合格,mg/kg,17-05-21 15:04;"; char *delim = ...
- HAL之串口
在STM32cubeMX中 1 外设功能打开 2 GPIO对应管脚的串口功能打开 3 对应GPIO引脚的配置 4串口的配置,中断的设置 在MDK中 5.1 串口初始化MX_USART1_UART_In ...
- azkaban web ui界面出现异常诡异“丑”界面的问题解决(图文详解)
前期博客 启动azkaban时出现User xml file conf/azkaban-users.xml doesn't exist问题解决(图文详解) 问题详情 [hadoop@master co ...
- 前端之HTML样式
<!doctype html> h5的文档声明 <html> 网页的根标签(根元素 html)--所有的代码都放置在此内 <head> <meta chars ...
- 问题处理:Cannot find module (SNMPv2-TC): At line 10 in /usr/share/snmp/mibs/UCD-DLMOD-MIB.txt
在执行 php -i |grep redis 时显示以下报错信息(但在phpinfo查看时一切正常): MIB search path: /root/.snmp/mibs:/usr/share/sn ...
- windows session logoff时进行处理动作
目标:Windows session logoff时得到通知,进行一些记录/清理工作 测试平台: win7 x64 logoff时系统会发送WM_ENDSESSION消息,如果某个应用对这个消息的处理 ...