[BZOJ1112] [POI2008] 砖块Klo (treap)
Description
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.
Input
第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000
Output
最小的动作次数
Sample Input
3
9
2
3
1
Sample Output
HINT
原题还要求输出结束状态时,每柱砖的高度.本题略去.
Source
Solution
妈丫BZOJ3224的$treap$调不出来只好另做一道$treap$简单题练手了。
欸这道题还能用树状数组做么?本蒟蒻不会丫。
这道题很容易想到,对于每一个区间,将区间内所有数改成该区间的中位数时开销最小。
找中位数就是找第$(k+1)/2$的数$mid$嘛,于是一个$treap$的做法就诞生了。
滑动窗口,每次保留$k$个数,求出比$mid$小的所有数的和$sum1$以及比$mid$大的所有数的和$sum2$
答案就是$(sum1-(比mid小的数的个数)*mid)+((比mid大的数的个数)*mid-sum2)$
欸好像可以化简,可以化简成$sum2-sum1$,$k$是偶数时多减一个$mid$
普通$treap$,记一个$siz$和一个$sum$即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct treap
{
int l, r, siz, val, pri;
ll key, sum;
}a[];
int root, ptot, h[];
ll sum1, sum2; void push_up(int k)
{
a[k].siz = a[a[k].l].siz + a[a[k].r].siz + a[k].val;
a[k].sum = a[a[k].l].sum + a[a[k].r].sum + a[k].key * a[k].val;
} void lturn(int &k)
{
int tmp = a[k].r;
a[k].r = a[tmp].l, a[tmp].l = k;
a[tmp].siz = a[k].siz, a[tmp].sum = a[k].sum;
push_up(k), k = tmp;
} void rturn(int &k)
{
int tmp = a[k].l;
a[k].l = a[tmp].r, a[tmp].r = k;
a[tmp].siz = a[k].siz, a[tmp].sum = a[k].sum;
push_up(k), k = tmp;
} void insert(int &k, int x)
{
if(!k)
{
k = ++ptot, a[k].siz = a[k].val = ;
a[k].sum = a[k].key = x, a[k].pri = rand();
return;
}
a[k].siz++, a[k].sum += x;
if(x == a[k].key) a[k].val++;
else if(x < a[k].key)
{
insert(a[k].l, x);
if(a[k].pri < a[a[k].l].pri) rturn(k);
}
else
{
insert(a[k].r, x);
if(a[k].pri < a[a[k].r].pri) lturn(k);
}
} void del(int &k, int x)
{
if(!k) return;
if(x == a[k].key)
if(a[k].val > ) a[k].val--, a[k].siz--, a[k].sum -= x;
else if(!(a[k].l * a[k].r)) k = a[k].l + a[k].r;
else if(a[a[k].l].pri < a[a[k].r].pri) lturn(k), del(k, x);
else rturn(k), del(k, x);
else if(x < a[k].key) a[k].siz--, a[k].sum -= x, del(a[k].l, x);
else a[k].siz--, a[k].sum -= x, del(a[k].r, x);
} int query_num(int k, int x)
{
if(!k) return ;
if(x <= a[a[k].l].siz)
{
sum2 += a[a[k].r].sum + a[k].key * a[k].val;
return query_num(a[k].l, x);
}
if(x <= a[a[k].l].siz + a[k].val)
{
sum1 += a[a[k].l].sum + (x - a[a[k].l].siz - ) * a[k].key;
sum2 += a[a[k].r].sum + (a[a[k].l].siz + a[k].val - x) * a[k].key;
return a[k].key;
}
sum1 += a[a[k].l].sum + a[k].key * a[k].val;
return query_num(a[k].r, x - a[a[k].l].siz - a[k].val);
} int main()
{
int n, k, mid;
ll ans = 100000000000000LL;
cin >> n >> k, srand(n);
for(int i = ; i <= n; i++)
cin >> h[i];
for(int i = ; i <= k; i++)
insert(root, h[i]);
for(int i = k + ; i <= n + ; i++)
{
sum1 = sum2 = ;
mid = query_num(root, (k + ) >> );
ans = min(ans, sum2 - sum1 - !(k & ) * mid);
insert(root, h[i]), del(root, h[i - k]);
}
cout << ans << endl;
return ;
}
[BZOJ1112] [POI2008] 砖块Klo (treap)的更多相关文章
- [BZOJ1112][POI2008]砖块Klo
[BZOJ1112][POI2008]砖块Klo 试题描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另 ...
- 【BZOJ1112】[POI2008]砖块Klo Treap
[BZOJ1112][POI2008]砖块Klo Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出 ...
- [Bzoj1112][POI2008]砖块Klo(splay)
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2353 Solved: 831[Submit][Statu ...
- BZOJ1112[POI2008]砖块Klo——非旋转treap
题目描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任 ...
- 【枚举】【权值分块】bzoj1112 [POI2008]砖块Klo
枚举长度为m的所有段,尝试用中位数更新答案. 所以需要数据结构,支持查询k大,以及大于/小于 k大值 的数的和. 平衡树.权值线段树.权值分块什么的随便呢. #include<cstdio> ...
- 【主席树】bzoj1112: [POI2008]砖块Klo
数据结构划一下水 Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. ...
- BZOJ 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1736 Solved: 606[Submit][Statu ...
- 1112: [POI2008]砖块Klo
1112: [POI2008]砖块Klo Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1245 Solved: 426[Submit][Statu ...
- [bzoj1112][POI2008]砖块Klo_非旋转Treap
砖块Klo bzoj-1112 POI-2008 题目大意:$N$柱砖,希望有连续$K$柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖 ...
随机推荐
- PHP实现session对象封装
<?php class Session { private $db; // 设置数据库变量 private $expiry = 3600; // 设置Session失效时间 public fun ...
- NSData所有API学习
www.MyException.Cn 网友分享于:2015-04-24 浏览:0次 NSData全部API学习. 学习NSData,在网上找资料竟然都是拷贝的纯代码,没人去解释.在这种网上 ...
- linux命令详解:pgrep命令
转载:http://www.th7.cn/system/lin/201311/46742.shtml 前言 经常要查看进程的信息,包括进程的是否已经消亡,通过pgrep来获得正在被调度的进程的相 ...
- jq模仿雨滴下落的动画
效果如图: 实现思路:定时器每隔x秒生成宽高.下落速度(即动画执行时间).left随机的div. 1.CSS: body{ overflow: hidden;/*这是为了防止出现滚动条*/ } .co ...
- 使用js dom和jquery分别实现简单增删改
<html><head> <meta http-equiv="Content-Type" content="text/html; chars ...
- 区间DP的四边形不等式优化
今天上课讲DP,所以我学习了四边形不等式优化(逃 首先我先写出满足四边形不等式优化的方程:
- Xen的虚拟化详解
最近在看Xen在2003年发表在sosp上的论文<Xen and the Art of Virtualization>,中途遇到一些不理解的技术点,在网络上查找相关资料,发现大多数人都只是 ...
- SpringMvc Ant通配符的使用
@RequestMapping使用通配符来对地址进行映射 Ant 的3风格 – ? 匹配文件名中的一个字符 – * 匹配文件名中的任意字符 – ** ** 匹配多重路径 例如:RequestMapp ...
- aforge 学习-命名空间中文理解
序列 名称 介绍 1 Aforge AForge AForge名称空间的核心名称空间.微软网络框架,其中包含核心类所使用的其他框架的命名空间和类,可以独立用于各种用途. 2 AForge.Cont ...
- PAT1118. Birds in Forest (并查集)
思路:并查集一套带走. AC代码 #include <stdio.h> #include <string.h> #include <algorithm> using ...