博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷 P3466 [POI2008]KLO-Building blocks
阅读量:4485 次
发布时间:2019-06-08

本文共 2698 字,大约阅读时间需要 8 分钟。

洛谷 P3466 [POI2008]KLO-Building blocks

题目:

  • 英文。转

题解:

  • fhq-treap,按权分裂。
  • 题目要求“连续K柱的高度是一样”,那么这个最终高度肯定是这K柱砖里的中位数。那么思绪就是枚举K柱砖的开头,求出每组砖的中位数,再求出花费。最终取一个最小花费。
  • 考虑优化,求动态中位数可以用对顶堆/平衡树,那么我选用fhq-treap。
  • 考虑优化,计算花费的思绪是暴力枚举K柱砖计算,其实观察可得到公式:花费 = (比mid小的数的个数 * mid - 比mid小的数之和) + (比mid大的数之和 - 比mid大的数的个数 * mid)。那么公式里涉及的几个量可以在平衡树更新过程中顺带更新出来。只需在结构体里开size和sum两个量,up操作时一起更新一下即可。
  • 所以此题选用fhq-treap解决问题。具体如何实现见代码
#include 
#include
#include
#define N 100005#define int long long#define inf 1e11using namespace std;struct T {int l, r, val, dat, size, sum;} t[N];int n, k, pos, root, tot, x, y, z, tim = inf, st, ans;int a[N];int read(){ int x = 0; char c = getchar(); while(c < '0' || c > '9') c = getchar(); while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();} return x;}int New(int val){ t[++tot].val = val, t[tot].dat = rand(); t[tot].size = 1, t[tot].sum = val; return tot;}void up(int p){ t[p].size = t[t[p].l].size + t[t[p].r].size + 1; t[p].sum = t[t[p].l].sum + t[t[p].r].sum + t[p].val;}void split(int p, int val, int &x, int &y){ if(!p) {x = y = 0; return;} if(t[p].val <= val) { x = p; split(t[p].r, val, t[p].r, y); } else { y = p; split(t[p].l, val, x, t[p].l); } up(p);}int merge(int x, int y){ if(!x || !y) return x + y; if(t[x].dat > t[y].dat) { t[x].r = merge(t[x].r, y); up(x); return x; } else { t[y].l = merge(x, t[y].l); up(y); return y; }}void insert(int val){ split(root, val, x, y); root = merge(merge(x, New(val)), y);}void erase(int val){ split(root, val, x, z); split(x, val - 1, x, y); y = merge(t[y].l, t[y].r); root = merge(merge(x, y), z);}int valOfRank(int rank){ int p = root; while(p) { if(t[t[p].l].size >= rank) p = t[p].l; else if(t[t[p].l].size + 1 == rank) break; else rank -= t[t[p].l].size + 1, p = t[p].r; } return t[p].val;}int cal(int mid){ split(root, mid - 1, x, y); split(y, mid, y, z); int ans = (t[x].size * mid - t[x].sum) + (t[z].sum - t[z].size * mid); root = merge(x, merge(y, z)); return ans;}signed main(){ cin >> n >> k, pos = (k + 1) / 2; for(int i = 1; i < k; i++) a[i] = read(), insert(a[i]); for(int i = k; i <= n; i++) { a[i] = read(), insert(a[i]); int mid = valOfRank(pos), val = cal(mid); if(val < tim) tim = val, ans = mid, st = i - k + 1; erase(a[i - k + 1]); } for(int i = st; i <= st + k - 1; i++) a[i] = ans; cout << tim << endl; for(int i = 1; i <= n; i++) printf("%lld\n", a[i]); return 0;}

转载于:https://www.cnblogs.com/BigYellowDog/p/11335706.html

你可能感兴趣的文章
文件锁
查看>>
props和state
查看>>
LeetCode:Unique Paths I II
查看>>
AcWing 兔子与兔子
查看>>
洛谷 P3871 [TJOI2010]中位数
查看>>
洛谷 P2073 送花
查看>>
洛谷 P1801 黑匣子_NOI导刊2010提高(06)
查看>>
洛谷 P1503 鬼子进村
查看>>
E. The shortest problem
查看>>
进制转换——9018——1065
查看>>
老男孩Python全栈开发(92天全)视频教程 自学笔记21
查看>>
ASP.NET页面传值之Server.Transfer 和Response.Direct
查看>>
git随笔
查看>>
codeforces 985C. Liebig's Barrels
查看>>
获取URL参数
查看>>
异步数据处理Handler
查看>>
线段树lazy标记??Hdu4902
查看>>
Google Map API 学习四
查看>>
Hibernate入门1
查看>>
filbeat遇到的坑(运行久和文件数据量多时候 )
查看>>