http://poj.org/problem?id=3709 (题目链接)

题意

  给出一个n个数的序列,要求将其中一些数改为另一个比它小的数,改动的花费为两数的绝对值,完成改动后使得整个序列中出现过的数出现的次数大于等于K。求最小花费。

Solution

  将原序列从大到小排序以后,我们可以发现,每次把连续的一段改成相同的数总是比离散的修改更优。于是我们写出dp方程:${f[i]=Min(f[j]+s[i]-s[j]-a[i]*(i-j))}$。${f[i]}$表示将前${i}$个数修改,并且第${i}$个数保持不变的最小费用;${s[i]}$表示前缀和;${a[i]}$表示第${i}$个数的值。

  考虑优化。斜率式:${-a[i]*j+f[i]=(f[j]-s[j])+s[i]-a[i]*i}$。

  然而我们发现斜率${-a[i]}$并不是单调的,所以就不能够直接取单调队列队首的元素了,那怎么办呢?只好在队列中二分了,二分的过程很好理解,详情见代码。

  以上作废,我在说什么鬼话→_→,${-a[i]}$显然是单调的。。

  再附张图,这次的单调队列里面的点构成的图形有点鬼。。竟然是个类似于反比例函数的东西→_→

细节

  记得开long long。。。

代码

// poj3709
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 1ll<<60
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=500010;
LL a[maxn],f[maxn],s[maxn];
int n,K,q[maxn]; bool cmp(int a,int b) {
return a>b;
}
double slope(int x,int y) {
return (double)((f[y]-s[y])-(f[x]-s[x]))/(double)(y-x);
}
int main() {
int T;scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&K);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+1+n,cmp);
for (int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
for (int i=1;i<=n;i++) f[i]=inf;
int l=1,r=1;q[1]=0;
for (int i=K;i<=n;i++) {
while (l<r && slope(q[l],q[l+1])<-a[i]) l++;
f[i]=f[q[l]]+s[i]-s[q[l]]-a[i]*(i-q[l]);
while (l<r && slope(q[r-1],q[r])>slope(q[r],i-K+1)) r--;
q[++r]=i-K+1;
}
printf("%lld\n",f[n]);
}
return 0;
}

代码(强行二分)

// poj3709
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 1e18
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=500010;
LL f[maxn],s[maxn],a[maxn];
int q[maxn],n,K; double slope(int x,int y) {
return (double)((f[y]-s[y])-(f[x]-s[x]))/(double)(y-x);
}
int find(int l,int r,LL x) {
int res=l;
while (l<=r) {
int mid=(l+r)>>1;
if (mid<r && x>slope(q[mid],q[mid+1])) l=mid+1,res=mid;
else if (mid>l && x<slope(q[mid-1],q[mid])) r=mid-1,res=mid;
else return mid;
}
return res;
}
bool cmp(LL a,LL b) {
return a>b;
}
int main() {
int T;scanf("%d",&T);
while (T--) {
scanf("%d%d",&n,&K);
for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
sort(a+1,a+1+n,cmp);
for (int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
for (int i=1;i<=n;i++) f[i]=inf;
int l=1,r=1;q[1]=0;
for (int i=K;i<=n;i++) {
int x=find(l,r,-a[i]);
f[i]=f[q[x]]+s[i]-s[q[x]]-a[i]*(i-q[x]);
while (l<r && slope(q[r-1],q[r])>slope(q[r],i-K+1)) r--;
q[++r]=i-K+1;
}
printf("%lld\n",f[n]);
}
return 0;
}

  

【poj3709】 K-Anonymous Sequence的更多相关文章

  1. 【CF486E】LIS of Sequence题解

    [CF486E]LIS of Sequence题解 题目链接 题意: 给你一个长度为n的序列a1,a2,...,an,你需要把这n个元素分成三类:1,2,3: 1:所有的最长上升子序列都不包含这个元素 ...

  2. 【BZOJ3110】K大数查询(整体二分)

    [BZOJ3110]K大数查询(整体二分) 题面 BZOJ 题解 看了很久整体二分 一直不知道哪里写错了 ... 又把树状数组当成线段树区间加法来用了.. 整体二分还是要想清楚在干什么: 我们考虑第\ ...

  3. 【CF1133E】K Balanced Teams(动态规划,单调队列)

    [CF1133E]K Balanced Teams(动态规划,单调队列) 题面 CF 让你把一堆数选一些出来分成不超过\(K\)组,每一组里面的最大值和最小值之差不超过\(5\),求最多有多少个人元素 ...

  4. 【BZOJ4355】Play with sequence 线段树

    [BZOJ4355]Play with sequence Description 维护一个长度为N的序列a,现在有三种操作: 1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a ...

  5. 【BZOJ4520】K远点对(KD-Tree)

    [BZOJ4520]K远点对(KD-Tree) 题面 BZOJ 洛谷 题解 考虑暴力. 维护一个大小为\(K\)的小根堆,然后每次把两个点之间的距离插进去,然后弹出堆顶 这样子可以用\(KD-Tree ...

  6. 【BZOJ4504】K个串 可持久化线段树+堆

    [BZOJ4504]K个串 Description 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计其子串中所有数字之和(注意这里重复出现的数字只被统计 ...

  7. 【题解】Cut the Sequence(贪心区间覆盖)

    [题解]Cut the Sequence(贪心区间覆盖) POJ - 3017 题意: 给定一大堆线段,问用这些线段覆盖一个连续区间1-x的最小使用线段的数量. 题解 考虑一个这样的贪心: 先按照左端 ...

  8. 【规律】A Rational Sequence

    题目描述 An infinite full binary tree labeled by positive rational numbers is defi ned by:• The label of ...

  9. 【动态规划】XMU 1583 Sequence

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1583 题目大意: T组数据,对于n(n<=6000)给定序列Xn(Xn<= ...

  10. 【SPOJ】2319 BIGSEQ - Sequence

    [算法]数位DP [题解]动态规划 题目要求的是大整数……没办法只写了小数字的,感觉应该没错. 大题框架是最大值最小化的二分问题. 对于每一块要求count(b)-count(a-1)≥s 已知a如何 ...

随机推荐

  1. Use Cursor

    declare : CURSOR cursor_name IS select_statement ; open : OPEN cursor_name if the query returns no r ...

  2. java多线程系类:基础篇:02常用的实现多线程的两种方式

    本章,我们学习"常用的实现多线程的2种方式":Thread 和 Runnable.之所以说是常用的,是因为通过还可以通过java.util.concurrent包中的线程池来实现多 ...

  3. sublime text2 打开包含中文的文件会自动追加.dump后缀解决办法

    用sublime text2 打开.c, .h,.txt等文件会自动追加一个.dump后缀,這样在打开.c,.h等文件时无法正常识别,从而无法正常进行语法着色,网上说是因为安装了GBK Encodin ...

  4. swift-sharesdk集成微信、Facebook第三方登录

    好久没有写博客了.最近忙得没有时间更新博客,很忙很忙. 今天就把自己做过的第三方集成和大家分享一下,请大家多多指教. 第一步: 一.获取AppKey(去官方平台注册) 二.下载SDK 三.快速集成 第 ...

  5. Oracle date 和 timestamp 区别

    1.DATE数据类型 这个数据类型我们实在是太熟悉了,当我们需要表示日期和时间的话都会想到date类型.它可以存储月,年,日,世纪,时,分和秒.它典型地用来表示什么时候事情已经发生或将要发生.    ...

  6. 在线音乐网站【03】Part one 功能实现

    今天打算把网站功能的具体实现给总结一下,如果你想了解整个小项目,建议你先看看前面2篇博客. 1.在线音乐网站(1)需求和功能结构 2.在线音乐网站(2)数据库和开发环境 7.网站主要模块实现 a.在线 ...

  7. Canvas之打字机游戏

    最近针对粒子化作了一点点的探究,决定结合其做个小游戏,于是这个简单的打字游戏出世了. 试玩地址:Typewriter game  仅在chrome下测试,请谨慎使用其他浏览器(特别是ff):加载速度有 ...

  8. Ace - Responsive Admin Template

    Ace简介: Ace 是一个轻量.功能丰富.HTML5.响应式.支持手机及平板电脑上浏览的管理后台模板,基于CSS框架Bootstrap制作,Bootstrap版本更新至 3.0,Ace – Resp ...

  9. Laravel 安装多国语言包后,phpstorm 还是报错

    问题: 解决办法: vagrant@homestead:~/Code/awbeci$ composer require "overtrue/laravel-lang:~3.0" 总 ...

  10. 基于Laravel+Swoole开发智能家居后端

    基于Laravel+Swoole开发智能家居后端 在上一篇<Laravel如何优雅的使用Swoole>中我已经大概谈到了Laravel结合Swoole的用法. 今天,我参与的智能家居项目基 ...