【uoj#280】[UTR #2]题目难度提升 对顶堆+STL-set
给出 $n$ 个数 $a_1,a_2,...,a_n$ ,将其排为序列 $\{p_i\}$ ,满足 $\{前\ i\ 个数的中位数\}$ 单调不降。求字典序最大的 $\{p_i\}$ 。
其中,对于一个长度为 $m$ 的数列,若 $m$ 为奇数,则中位数为从小到大第 $\lceil\frac m2\rceil$ 大的数;若 $m$ 为偶数,则中位数为从小到大第 $\frac m2$ 大和第 $\frac m2+1$ 大的数的平均值。
题解
对顶堆+STL-set
显然如果已经知道了这个数列的一部分,剩下的一定是每次加入大于等于中位数的数。
那么如何确定这一“部分呢”?将 $a$ 从小到大排序,然后:
- 如果 $a_{\lceil\frac n2\rceil}=a_{\lceil\frac n2\rceil+1}$ ,则可以让任何时刻中位数都等于 $a_{\lceil\frac n2\rceil}$ ,找到最大的 $k$ 使得 $a_k+1=a_{\lceil\frac n2\rceil}$ ,按照 $k,k+1,k-1,k+2,k-2,...$ 的顺序选择完整个数列即可得到最优解,显然任何时刻中位数都相等。没有考虑到这种情况可以得到60分。
- 否则如果存在 $k<\lceil\frac n2\rceil$ 且 $a_k=a_{k+1}$ ,则按照 $k,k+1,k-1,k+2,k-2,...$ 的顺序选择,直到前面没有数可以取,这个过程中位数都相等。没有考虑到这种情况只能得到所有数互不相同的40分。
- 否则选择第一个数。
然后使用multiset保证每次删除后最小的数大于等于中位数,使用对顶堆维护中位数即可。
对顶堆:使用大根堆维护较小数,使用小根堆维护大数,保证两个堆的大小差不超过1。显然中位数可以直接从两个堆的堆顶元素得到。
时间复杂度 $O(n\log n)$ 。
#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
multiset<int> s;
priority_queue<int> A , B;
int a[N] , v[N];
inline void push(int x)
{
if(A.empty() || x <= A.top()) A.push(x);
else B.push(-x);
if(A.size() < B.size()) A.push(-B.top()) , B.pop();
if(A.size() - B.size() > 1) B.push(-A.top()) , A.pop();
}
int main()
{
int n , i , p , q , mid;
scanf("%d" , &n);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &a[i]);
sort(a + 1 , a + n + 1) , mid = (n + 1) >> 1;
if(a[mid] == a[mid + 1])
{
while(mid < n && a[mid] == a[mid + 1]) mid ++ ;
printf("%d" , a[mid]) , p = mid - 1 , q = n;
while(p || q > mid)
{
if(p) printf(" %d" , a[p -- ]);
if(q > mid) printf(" %d" , a[q -- ]);
}
return 0;
}
while(mid > 1 && a[mid] != a[mid - 1]) mid -- ;
printf("%d" , a[mid]) , v[mid] = 1 , p = mid - 1 , q = n;
while(p && q > mid) printf(" %d" , a[p]) , v[p -- ] = 1 , printf(" %d" , a[q]) , v[q -- ] = 1;
for(i = 1 ; i <= n ; i ++ )
{
if(v[i]) push(a[i]);
else s.insert(a[i]);
}
while(!s.empty())
{
p = *s.begin();
if(A.size() == B.size())
{
if(p >= -B.top()) q = *--s.end();
else q = *s.begin();
}
else
{
if(!B.empty() && p * 2 >= A.top() - B.top()) q = *--s.end();
else q = *--s.upper_bound(p * 2 - A.top());
}
printf(" %d" , q) , s.erase(s.find(q)) , push(q);
}
return 0;
}
【uoj#280】[UTR #2]题目难度提升 对顶堆+STL-set的更多相关文章
- 【UTR #2】[UOJ#278]题目排列顺序 [UOJ#279]题目交流通道 [UOJ#280]题目难度提升
[UOJ#278][UTR #2]题目排列顺序 试题描述 “又要出题了.” 宇宙出题中心主任 —— 吉米多出题斯基,坐在办公桌前策划即将到来的 UOI. 这场比赛有 n 道题,吉米多出题斯基需要决定这 ...
- uoj#280. 【UTR #2】题目难度提升(构造)
传送门 咱先膜一下\(GXZ\)再说 我们先把序列从小到大排序,然后分情况讨论 无解是不存在的,从小到大输出所有数肯定可行 情况一,如果\(a[mid]=a[mid+1]\),因为最终的中位数也是它们 ...
- 【UOJ #280】【UTR #2】题目难度提升
http://uoj.ac/problem/280 非常难想的贪心,用set\(O(nlogn)\). 调了一天qwq. 题解 #include<set> #include<cstd ...
- uoj280 【UTR #2】题目难度提升 堆维护中位数+set
题目传送门 http://uoj.ac/problem/280 题解 这道题很妙啊. 这种题目如果给予选手足够的时间,每一个选手应该都能做出来. 大概就是核心思路看上去很简单,但是想要推出来并不简单. ...
- 洛谷 - P1801 - 黑匣子 - 对顶堆
这道题是提高+省选-的难度,做出来的话对数据结构题目的理解会增加很多. 可以使用一种叫做对顶堆的东西,对顶堆是在线维护第n小的logn的算法.大概的思路是,假如我们要找的是第n小,我们就维护一个大小为 ...
- 【Luogu P1168】【Luogu P1801&UVA 501】中位数&黑匣子(Black Box)——对顶堆相关
Luogu P1168 Luogu P1801 UVA 501(洛谷Remote Judge) 前置知识:堆.优先队列STL的使用 对顶堆 是一种在线维护第\(k\)小的算法. 其实就是开两个堆,一个 ...
- poj3784(对顶堆)
题意:多组数据,让你求出1~i(i为奇数&&i<=n)的中位数 思路:首先复杂度必为O(n)或O(nlogn)的(数据范围) 思索,如果题目要求1次中位数,好求!排个序,取a[( ...
- hdu3282 链表或者对顶堆
维护序列的动态中位数 第一次用链表做题..感觉指针指来指去也挺麻烦的.. 本题链表解法就是用数组模拟出一个链表,然后离线输入所有数,排序,按照输入顺序在链表里删除元素,一次性删掉两个,然后中位数指针对 ...
- hdu4261 Estimation[暴力dp+对顶堆]
https://vjudge.net/problem/HDU-4261 对于一个长2000的数列划分最多25个块,每块代价为块内每个数与块内中位数差的绝对值之和,求最小总代价. 套路化地,设$f[i] ...
随机推荐
- Android Studio 重命名文件
选中文件,Refactor——Rename AS提供了两种方式重命名,Rename 和 Rename File,暂时还不清楚区别.有知道的麻烦告知下.
- 腾讯x5webview集成实战
应用中许多网页由于优化的不够理想,出现加载慢,加载时间长等,而且因为碎片化导致兼容性问题,有一些网页有视频内容,产品还提出各种小窗需求,搞得心力憔悴.找到公开的有crosswalk和x5webview ...
- 用人工智能学习,凡亿推出PCB问题解答智能搜索机器人:pcb助手
对于学习者,你是不是经常遇到这样的问题:在我们狠狠下定决心学习PCB技术的时候,我们常常遇到很多大大小小的问题,遗憾的是身边没有一个能及时给自己解答问题的高手指点,通过论坛.群等方式询问可能半天也得不 ...
- hashCode及HashMap中的hash()函数
一.hashcode是什么 要理解hashcode首先要理解hash表这个概念 1. 哈希表 hash表也称散列表(Hash table),是根据关键码值(Key value)而直接进行访问的数据结构 ...
- 基础:enctype 包含上传input时必须(解决图片上传不成功问题)
今天在做一个上传图片的时候,死活就是看不到传过去的值..对比了写法没发现问题,后来抱着试试看的心,查看下了 from里的写法.发现缺少了enctype.不了解这个用法,特意百度了下. enctype ...
- L2 Helios OPcodez
天堂2 Helios太阳神版本 的客户端和服务端封包 *********************** Client ***********************00 SendLogOut01 Req ...
- XML学习(一)
实体引用 在 XML 中,一些字符拥有特殊的意义. 如果您把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始. 这样会产生 XML 错误: ...
- 从零开始的Python学习Episode 19——面向对象(2)
面向对象之继承 继承是一种创建新类的方式,新建的类可以继承一个或多个父类(python支持多继承),父类又可称 为基类或超类,新建的类称为派生类或子类. 子类会“”遗传”父类的属性,从而解决代码重用问 ...
- PCL 库存在vtk的问题导致libproj.so链接错误
常变现为** No rule to make target '/usr/lib/x86_64-linux-gnu/libproj.so', needed by ××× vtk库的bug导致,目前尚未修 ...
- 吴恩达 Deep learning 第二周 神经网络基础
逻辑回归代价函数(损失函数)的几个求导特性 1.对于sigmoid函数 2.对于以下函数 3.线性回归与逻辑回归的神经网络图表示 利用Numpy向量化运算与for循环运算的显著差距 import nu ...