【主席树】bzoj1112: [POI2008]砖块Klo
数据结构划一下水
Description
N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任务.
Input
第一行给出N,K. (1 ≤ k ≤ n ≤ 100000), 下面N行,每行代表这柱砖的高度.0 ≤ hi ≤ 1000000
Output
最小的动作次数
题目大意
有一个非负的数列,可以±1修改高度,求最小代价使得连续k个高度相同
题目分析
对于一个区间的答案,就相当于把所有数都放在数轴上,再求一个数使得它到所有数的总和最小。那么最优就等于是求一个区间的中位数。
于是问题相当于一个支持 求中位数;求比中位数小/大的数个数;求比中位数小/大的数总和 的数据结构。这个问题可以用主席树在$logn$内完成。
注意 printf(calc(),a,b) ,如果在calc()中改变了a,b,输出的a,b将会是改变之前的值。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = ;
const int maxNode = ; struct node
{
int val,l,r;
ll sum;
}a[maxNode];
ll ans,lsum,rsum,lcnt,rcnt;
int n,k;
int rt[maxn],w[maxn],cnt[maxn],tot; int read()
{
char ch = getchar();
int num = , fl = ;
for (; !isdigit(ch); ch=getchar())
if (ch=='-') fl = -;
for (; isdigit(ch); ch=getchar())
num = (num<<)+(num<<)+ch-;
return num*fl;
}
void build(int &rt, int l, int r)
{
rt = ++tot;
if (l==r) return;
int mid = (l+r)>>;
build(a[rt].l, l, mid);
build(a[rt].r, mid+, r);
}
void update(int pre, int &rt, int l, int r, int c)
{
rt = ++tot, a[rt] = a[pre], ++a[rt].val, a[rt].sum += cnt[c];
if (l==r) return;
int mid = (l+r)>>;
if (c <= mid) update(a[pre].l, a[rt].l, l, mid, c);
else update(a[pre].r, a[rt].r, mid+, r, c);
}
int query(int pre, int rt, int l, int r, int k)
{
if (l==r) return l;
int val = a[a[rt].l].val-a[a[pre].l].val, mid = (l+r)>>;
if (val >= k){
lcnt -= a[a[rt].r].val-a[a[pre].r].val;
lsum -= a[a[rt].r].sum-a[a[pre].r].sum;
return query(a[pre].l, a[rt].l, l, mid, k);
}
rcnt -= a[a[rt].l].val-a[a[pre].l].val;
rsum -= a[a[rt].l].sum-a[a[pre].l].sum;
return query(a[pre].r, a[rt].r, mid+, r, k-val);
}
int main()
{
n = read(), k = read(), ans = 1ll<<;
for (int i=; i<=n; i++) w[i] = cnt[i] = read();
std::sort(cnt+, cnt+n+);
cnt[] = std::unique(cnt+, cnt+n+)-cnt-;
build(rt[], , cnt[]);
for (int i=; i<=n; i++)
{
w[i] = std::lower_bound(cnt+, cnt+cnt[]+, w[i])-cnt;
update(rt[i-], rt[i], , cnt[], w[i]);
}
for (int r=k; r<=n; r++)
{
int l = r-k;
lcnt = rcnt = a[rt[r]].val-a[rt[l]].val, lsum = rsum = a[rt[r]].sum-a[rt[l]].sum;
int tmp = cnt[query(rt[l], rt[r], , cnt[], (k+)>>)];
ans = std::min(ans, 1ll*tmp*(lcnt-rcnt)-lsum+rsum);
}
printf("%lld\n",ans);
return ;
}
END
【主席树】bzoj1112: [POI2008]砖块Klo的更多相关文章
- [BZOJ1112][POI2008]砖块Klo
[BZOJ1112][POI2008]砖块Klo 试题描述 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)
Description N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次 ...
- 【枚举】【权值分块】bzoj1112 [POI2008]砖块Klo
枚举长度为m的所有段,尝试用中位数更新答案. 所以需要数据结构,支持查询k大,以及大于/小于 k大值 的数的和. 平衡树.权值线段树.权值分块什么的随便呢. #include<cstdio> ...
- BZOJ1112[POI2008]砖块Klo——非旋转treap
题目描述 N柱砖,希望有连续K柱的高度是一样的. 你可以选择以下两个动作 1:从某柱砖的顶端拿一块砖出来,丢掉不要了. 2:从仓库中拿出一块砖,放到另一柱.仓库无限大. 现在希望用最小次数的动作完成任 ...
- 【BZOJ1112】[POI2008]砖块Klo Treap
[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 ...
- BZOJ 1112 [POI2008]砖块Klo(可持久化线段树)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1112 [题目大意] 给出一个数列,对于一个操作,你可以对一个数+1,或者一个数-1, ...
随机推荐
- plsql developer 执行sql 文件
用 Command Window,执行 @'sql file path' 注意,上面sql文件路径要加单引号
- C# 操作 Excel 文件(.xls 或 .xlsx)
在.net中,常用的操作excel文件的方式,有三种: OLE DB的形式, 第三方框架NPOI, Office组件. 总结: 通过对比,在读取大数据量的excel文件,建议用OLE DB的形式,把e ...
- CC22:检查是否为BST
题目 请实现一个函数,检查一棵二叉树是否为二叉查找树. 给定树的根结点指针TreeNode* root,请返回一个bool,代表该树是否为二叉查找树. 解法 二叉排序树有个特点是,结点通过中序遍历出来 ...
- 题解 poj3585 Accumulation Degree (树形dp)(二次扫描和换根法)
写一篇题解,以纪念调了一个小时的经历(就是因为边的数组没有乘2 phhhh QAQ) 题目 题目大意:找一个点使得从这个点出发作为源点,流出的流量最大,输出这个最大的流量. 以这道题来介绍二次扫描和换 ...
- 牛客假日团队赛2 D.亲和数对
链接: https://ac.nowcoder.com/acm/contest/924/D 题意: 求在给定区间[start,end]内所有的亲和数对. 亲和数的定义:对于数对(A,B),如果A的除了 ...
- 线程池ThreadPoolExecutor的学习
我们知道,ExecutorService是一个抽象出线程池的一个接口,然后我们在使用线程池的时候,用的是Executors工具类中的一系列newCachedThreadPool() 等类似的方法,这些 ...
- 《从0到1学习Flink》—— Mac 上搭建 Flink 1.6.0 环境并构建运行简单程序入门
准备工作 1.安装查看 Java 的版本号,推荐使用 Java 8. 安装 Flink 2.在 Mac OS X 上安装 Flink 是非常方便的.推荐通过 homebrew 来安装. brew in ...
- Android ORM对象关系映射之GreenDAO建立多表关联
https://blog.csdn.net/u010687392/article/details/48496299 利用GreenDAO可以非常方便的建立多张表之间的关联 一对一关联 通常我们在操作数 ...
- 初识RatingBar
RatingBar,SeekBar和ProgressBar的子类 <RatingBar android:id="@+id/ratingBar2" android:layout ...
- 设置DIV随滚动条滚动而滚动
有段时间没有碰Web端了,最近做了个功能,需要做个DIV随滚动条滚动而滚动,mark一下: 源码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...