坑爹的BZOJ因为不让 输出方案我WA了若干次

据说正解是平衡树/线段树,我不会,就用了个新东西—>对顶堆

对顶堆

一个维护中位数的东西,我们通过维护两个堆,来维所有数的中位数
(显然我们可以排个序)

具体实现:

我们维护一个大根堆,把所有小于等于中位数的数放进去,堆顶就是中位数,你会问,为什么会是中位数?我们保证这个堆中的元素个数始终为(n+1)/2个,两个堆元素个数一共为n所以这个堆的堆顶就是中位数,另一个堆是小根堆,维护的所有大于中位数的数放进去,中位数在填完最后一个数之前把那个不是固定的,所以我们要等到所有数加完后,取第一个堆的堆顶元素就好了

具体操作:

先考虑 整个数列 ,不带删除的情况,每加入一个元素,我们先判断放小数的堆是否够了(k+1)/2个,不够就要先放进去,然后够了之后,每次加入一个元素 ,判断和大根堆堆顶的关系,比他大说明比目前的中位数要大,所以放到小根堆中,小的话就放到大根堆中,然后我们发现这时大根堆的元素多了,那么我们就要把大根堆的堆顶放到小根堆中,这样仍然满足性质

然后是部分区间的中位数,就是我们这道题
不难发现 ,把一段连续区间修改为他们的中位数是最优的,所以我们就可以维护每个长度为k的区间修改为中位数的花费,区间移动就涉及到了删除元素的操作 ,但是我们又找不到上一个元素具体在什么位置,怎么办?我们不再用堆的size表示堆中元素个数,我们用两个变量siz1,siz2表示两个堆的大小,然后我们发现,只要删除元素不在堆顶,他在什么位置是没有关系的,所以我们只需呀给他打上标记,然后等他到堆顶时,直接pop掉 就好了,打标记 的同时也要给它所在堆的siz–,判断 所在堆的方法是比较删除元素于大根堆堆顶的大小关系,也就是和在中位数的大小关系
然后这时你可能会说,我们维护了中位数,怎么统计答案呢?我们将求花费的式子列出来并化简得到ans=∑i=1(i+k+1)/2mid−a[i]\sum_{i=1}^{(i+k+1)/2}mid-a[i]∑i=1(i+k+1)/2​mid−a[i]+∑i=(i+k+1)/2+1i+k\sum_{i=(i+k+1)/2+1}^{i+k}∑i=(i+k+1)/2+1i+k​,然后发现它等于比mid小的数的个数∗\ast∗mid-比mid小的数的和+比mid大的数的和-mid∗\ast∗比mid大的数的个数,个数很好说就是两个堆的大小,和呢?我们 也维护两个值sum1和sum2,表示两个堆的大小,插入和删除时,一块修改就好了

代码

//By AcerMo
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define t1 q1.top()
#define t2 q2.top()
#define grtr greater
#define lli long long int
using namespace std;
const int M=200500;
int n,m;
int a[M],vis[M*10];
lli si1,si2,su1,su2;
priority_queue<int,vector<int>,less<int> >q1;//大根堆,保证堆顶是所有小数的最大值
priority_queue<int,vector<int>,grtr<int> >q2;//小根堆,保证堆顶是所有大数的最小值
inline int read()
{int x=0;char ch=getchar();while (ch>'9'||ch<'0') ch=getchar();while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();return x;
}
inline void write(lli x)
{if (x>9) write(x/10);putchar(x%10+'0');return ;
}
inline void update()
{if (q1.size()) while (vis[t1]&&q1.size()) vis[t1]--,q1.pop();if (q2.size())while (vis[t2]&&q2.size()) vis[t2]--,q2.pop();return ;
}//清除堆顶的删除元素
inline void add(int x)
{update();while (si1<(m+1)/2&&si2) {int y=t2;q2.pop();q1.push(y);si1++;si2--;su2-=y;su1+=y;update();}//将大根堆的元素加到中位数的位置上(m+1)/2中位数的位置if (si1==0){si1++;su1+=x;return (void)(q1.push(x));}//这个情况只有在两个堆都是空的的时候会出现,优先放在小数的里if (x<q1.top()) si1++,su1+=x,q1.push(x);//比大根堆的最大值要小,那么肯定不能放在小根堆里else si2++,su2+=x,q2.push(x);//不然就放在小根堆里,因为我们已经调整过siz了update();while (si1>(m+1)/2&&si1){int y=t1;q1.pop();q2.push(y);si1--;si2++;su1-=y;su2+=y;update();}//然后调整一下大根堆 ,防止多了update();while (si1<(m+1)/2&&si2){int y=t2;q2.pop();q1.push(y);si1++;si2--;su1+=y;su2-=y;update();}//也可能是一开始没有调整,然后在这次加入了小根堆,那么我们在先满足大根堆的前提下 ,就把他拿过来就好return (void)(update());
}
inline void del(int x)
{vis[x]++;if (x>q1.top()) si2--,su2-=x;else si1--,su1-=x;return (void)(update());
}//删除打个标记就行了
inline lli calc(lli x)
{lli tot=su2-(lli)m/2*x;tot+=(lli)(m+1)/2*x-su1;return tot;
}//计算公式:比中位数小的数的个数*中位数大小-比中位数小的数的和//+比中位数大的数的和-比中位数大的数的个数*中位数
signed main()
{n=read();m=read();for (int i=1;i<=n;i++) a[i]=read();for (int i=1;i<=m;i++) add(a[i]);lli mid,l=1,r=m,ans=t1;lli tot=su2-(lli)m/2*ans; tot+=(lli)(m+1)/2*ans-su1;for (int i=m+1;i<=n;i++){del(a[i-m]);add(a[i]);mid=t1;lli cnt=calc(mid);if (tot>=cnt&&cnt>=0) tot=cnt,l=i-m+1,r=i,ans=mid;}write(tot);puts("");/*for (int i=1;i<=n;i++)if (i>=l&&i<=r) write(ans),puts("");else write(a[i]),puts("");*/ //BZ这里要删掉return 0;
}

BZOJ1112洛谷P3466 [POI2008]KLO-Building blocks(砖头)[对顶堆学习笔记]相关推荐

  1. 洛谷 P3466 [POI2008]KLO-Building blocks

    洛谷 P3466 [POI2008]KLO-Building blocks 题目: 英文.转链接 题解: fhq-treap,按权分裂. 题目要求"连续K柱的高度是一样",那么这个 ...

  2. 洛谷 P3466 [POI2008]KLO-Building blocks 支持删除的堆

    题面 这题怎么人均fhqfhqfhq啊,让STLSTLSTL选手情何以堪? 于是就来一发priorityprioritypriority_queuequeuequeue+map的题解吧(突然发现map ...

  3. BZOJ1112: [POI2008]砖块Klo(洛谷P3466)

    平衡树 BZOJ题目传送门 洛谷题目传送门 动态维护中位数,平衡树上一发就好了. 代码: #include<cctype> #include<cstdio> #include& ...

  4. 洛谷 P2440 木材加工(二分,含边界处理的笔记)

     题目链接: 木材加工 - 洛谷https://www.luogu.com.cn/problem/P2440 非常简单的题目,用left和right控制二分边界,ans一开始是0,每次check到符合 ...

  5. 洛谷 P3469 [POI2008]BLO-Blockade (Tarjan,割点)

    P3469 [POI2008]BLO-Blockade https://www.luogu.org/problem/P3469 题目描述 There are exactly nn towns in B ...

  6. 洛谷 P3469 [POI2008]BLO-Blockade

    思路 这个题有点吓人呢先在这里默认大家都会tarjan找割点了哈 如果你跑tarjantarjantarjan找割点然后把割点删掉跑bfsbfsbfs找连通块,这个O(n2)O(n^2)O(n2)显然 ...

  7. 洛谷P3469 [POI2008]BLO-Blockade(割点过程计算bcc)

    思路:去掉点 i i i后,其他点无论如何都无法到达它了,所以答案首先是 2 ∗ ( n − 1 ) 2*(n-1) 2∗(n−1). 其次,考虑这个点去掉之后,是否会造成一个点无法到达其他点了呢?也 ...

  8. 洛谷日报 2020年3月前索引

    2020 2019 2018 感觉洛谷日报全是干货!!!先记下来再说 2020 年洛谷日报索引 3 月 #260[dove]Church 编码(和 Lambda 演算) https://www.luo ...

  9. 洛谷日报索引(2020、2019、2018)

    历年洛谷日报索引 2020 2019 2018 感觉洛谷日报全是干货!!!先记下来再说 2020 年洛谷日报索引 3 月 #260[dove]Church 编码(和 Lambda 演算) https: ...

最新文章

  1. AIR for IOS开发问题小结
  2. Codeforces Round #673 (Div. 2)——待补 E
  3. python twisted教程_Python Twisted系列教程1:Twisted理论基础
  4. 思考 | 沈向洋博士:三十年科研路,我踩过的那些坑
  5. 异常检测1——python使用KNN模型进行异常检测
  6. 29.奖金(拓扑排序)
  7. 2008r2服务器频繁自动重启,关于Windows server2008频繁重启问题
  8. 二手书交易系统功能结构图
  9. 《从0到1:CTFer成长之路》 配套题目Web WP
  10. 学游戏设计要什么学历_学历低学游戏动作设计好就业吗
  11. 创新设计思维——做出好产品的艺术
  12. vue中插值语法中v-for() of 与v-for() in 遍历对象数组的异同,以及for in for of在方法中遍历对象和数组的异同
  13. 可以ping通外网,ping不通内网,同时可以Ping网关,但是外部ping不到IP
  14. 【2018慢性病与信息大会】吴良友:信息化背景下慢性病监测工作变革
  15. 蓝桥杯项目一:可调闹钟1(详解版)
  16. Android 音频(Audio)架构
  17. 华为无线路由器信道怎么测试软件,教你为无线路由器选择合适的信道让上网更快...
  18. 解决Python打开文件报错UnicodeDecodeError: 'gbk' codec can't decode byte
  19. html 怪异模式,CSS_浅谈CSS编程中的怪异模式,怪异模式盒模型 今天学习了 - phpStudy...
  20. Linux squid构建-传统模式和透明模式部署

热门文章

  1. LSM优化系列(五) -- 【SIGMOD‘19】X-engine 在电商场景下针对大规模事务处理的优化-- 强者恒强啊
  2. 不动点法和牛顿法求方程的根——matlab实例
  3. 火爆全网:天池所有学习资源面世!
  4. 一文搞懂 位运算 异或(Java实现)
  5. Vim/Vi 编辑器,删除总结
  6. win10 c语言语音朗读,win10安装朗读女软件
  7. Postman 调试请求Asp.NetCore3.1WebApi Get/Post/Put/Delete文件上传等
  8. 企业级部署解决方案CRM 2011安装在Windows Server 2012
  9. 大红手促销机提高你的竞争实力
  10. 电脑扫描的文件怎么转换成word文档并修改