【poj3709】 K-Anonymous Sequence

时间:2023-01-01 21:37:52

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]}$显然是单调的。。

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

【poj3709】 K-Anonymous Sequence

细节

  记得开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&rpar;

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

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

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

  7. 【题解】Cut the Sequence&lpar;贪心区间覆盖&rpar;

    [题解]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. ajax循环读取json多维数组

    test.json: { "one": [ { "name": "黑默丁格", "car": "鲁LLL608 ...

  2. &lbrack;&period;net 面向对象程序设计进阶&rsqb; &lpar;6&rpar; Lamda表达式&lpar;二&rpar; 表达式树快速入门

    [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...

  3. 学习总结 java 异常

    package com.hanqi.ec; public class Test1 { public static void main(String[] args) { int a = 10 , b = ...

  4. A&ast;算法完全理解

    注:原文出自Patrick Lester,一稿翻译为Panic.很久以前的老文章了,但我觉得真的非常的经典,想把它完善一下让以后的人能够更好的体会原作者和原翻译的精髓吧.我在此基础上修改了部分译文,更 ...

  5. shell programs

    find * -not -path "docs/*" -regex ".*\.\(rb\)" -type f -print0 | xargs -0     gr ...

  6. Cocos2d-x在线粒子编辑器

    *.其效果是非常赞,可以手动调节和.出口可以上网plist档!. 住址:http://particle2dx.com/

  7. EF中的贪婪加载和延迟加载(懒加载)

    在上一章中,我们使用了Linq对Entity Framework进行了一个查询,但是通过学习我们却发现了懒加载给我来的性能上的开销是很到的,尤其是在循环中,如果数据量不是很多的情况下还可以接受,如果数 ...

  8. JS - 讨论 - 编码习惯 - JavaScript代码到底要不要写分号?

    如题:烦请大家在评论区给出原创意见!多谢!

  9. 配置VIP地址

    10.10.10.7  mysql主 redis从 10.10.10.8  mysql从 redis主 现游戏架构如上,游戏后端数据库配置集群.场景描述:若是一台服务器宕机之后,及时切换数据库保持业务 ...

  10. Spring的第三天AOP之xml版

    Spring的第三天AOP之xml版 ssm框架 spring  AOP介绍 AOP(Aspect Oriented Programming),面向切面编程.它出来的目的并不是去取代oop,而是对它的 ...